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]

[PATCH] auxv support


Ok, I think this is looking pretty polished now.  I've tested it on Linux
and Solaris.  On both systems I tested the live process case, the core file
case, and gcore.  I did not test a multithreaded Solaris program, so that
trivial part of the code path has not actually been exercised.

This adds the underlying support we talked about before, implemented
basically the same as my earlier patch.  It also adds the `info auxv'
command as Andrew proposed, but with slightly nicer output.  The function
for reading /proc/PID/auxv, and some of the other code previously
duplicated between the procfs and linux implementations, is now shared code
in auxv.c.  There is also a utility function there that is what's needed
for finding a single known tag's value, as some hook will do to check for
AT_SYSINFO_EHDR.

I would like to add remote protocol and gdbserver support as well, but
someone knowledgeable about gdbserver should ping me.


Solaris example output:

    (gdb) i aux
    2008 AT_SUN_PLATFORM      Platform name string           0xffbfffe1 "SUNW,Ultra-60"
    2014 AT_SUN_EXECNAME      Canonicalized file name given to execve 0xffbfffef "/usr/bin/cat"
    3    AT_PHDR              Program headers for program    0x10034
    4    AT_PHENT             Size of program header entry   32
    5    AT_PHNUM             Number of program headers      6
    9    AT_ENTRY             Entry point of program         0x10b3c
    2016 AT_SUN_LDDATA        Dynamic linker's data segment address 0x7fbf6000
    7    AT_BASE              Base address of interpreter    0x7fbc0000
    8    AT_FLAGS             Flags                          0x300
    6    AT_PAGESZ            System page size               8192
    2000 AT_SUN_UID           Effective user ID              3520
    2001 AT_SUN_RUID          Real user ID                   3520
    2002 AT_SUN_GID           Effective group ID             3520
    2003 AT_SUN_RGID          Real group ID                  3520
    2009 AT_SUN_HWCAP         Machine-dependent CPU capability hints 0x7
    0    AT_NULL              End of vector                  0x0
    0    AT_NULL              End of vector                  0x0
    0    AT_NULL              End of vector                  0x0
    0    AT_NULL              End of vector                  0x0
    (gdb) 

Linux example output:

    (gdb) i aux
    32   AT_SYSINFO           Special system info/entry points 0xffffe400
    33   AT_SYSINFO_EHDR      System-supplied DSO's ELF header 0xffffe000
    16   AT_HWCAP             Machine-dependent CPU capability hints 0x383fbff
    6    AT_PAGESZ            System page size               4096
    17   AT_CLKTCK            Frequency of times()           100
    3    AT_PHDR              Program headers for program    0x8048034
    4    AT_PHENT             Size of program header entry   32
    5    AT_PHNUM             Number of program headers      6
    7    AT_BASE              Base address of interpreter    0x40000000
    8    AT_FLAGS             Flags                          0x0
    9    AT_ENTRY             Entry point of program         0x8048ae0
    11   AT_UID               Real user ID                   5281
    12   AT_EUID              Effective user ID              5281
    13   AT_GID               Real group ID                  5281
    14   AT_EGID              Effective group ID             5281
    23   AT_SECURE            Boolean, was exec setuid-like? 0
    15   AT_PLATFORM          String identifying platform    0xbffffb20 "i686"
    0    AT_NULL              End of vector                  0x0
    (gdb) 

Not shown in either is the output for an unknown value, which there aren't
any since I've added all known values.  But it would look like this:

    99   ???                                                 0x12345678



Approved?


Thanks,
Roland


2004-01-28  Roland McGrath  <roland@redhat.com>

	* sol-thread.c (sol_thread_xfer_partial): New function.
	(init_sol_thread_ops): Use that for to_xfer_partial hook.
	(init_sol_core_ops): Likewise.

	* procfs.c (procfs_xfer_partial): New function.
	(init_procfs_ops): Use that for procfs_ops.to_xfer_partial.
	* Makefile.in (procfs.o): Add $(auxv_h) dep.

	* config/nm-linux.h (NATIVE_XFER_AUXV): New macro, uses auxv.c's
	procfs_xfer_auxv function.

	* procfs.c (procfs_make_note_section): If we can read
	TARGET_OBJECT_AUXV data, add an NT_AUXV note containing it.
	* linux-proc.c (linux_make_note_section): Likewise.

	* auxv.h: New file.
	* auxv.c: New file.
	* Makefile.in (auxv_h): New variable.
	(COMMON_OBS): Add auxv.o here.
	(auxv.o): New target.

	* corelow.c (core_xfer_partial): New function.
	(init_core_ops): Use it for core_ops.to_xfer_partial.

	* target.h (enum target_object): Add TARGET_OBJECT_AUXV.
	* inftarg.c (child_xfer_partial): Support it using NATIVE_XFER_AUXV
	macro if that is defined.

Index: auxv.c
===================================================================
RCS file: auxv.c
diff -N auxv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ auxv.c	29 Jan 2004 02:48:03 -0000
@@ -0,0 +1,301 @@
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "target.h"
+#include "gdbtypes.h"
+#include "command.h"
+#include "inferior.h"
+#include "valprint.h"
+#include "gdb_assert.h"
+
+#include "auxv.h"
+#include "elf/common.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+
+/* This function is called like a to_xfer_partial hook,
+   but must be called with TARGET_OBJECT_AUXV.
+   It handles access via /proc/PID/auxv, which is the common method.
+   This function is appropriate for doing:
+	   #define NATIVE_XFER_AUXV	procfs_xfer_auxv
+   for a native target that uses inftarg.c's child_xfer_partial hook.  */
+
+LONGEST
+procfs_xfer_auxv (struct target_ops *ops,
+		  int /* enum target_object */ object,
+		  const char *annex,
+		  void *readbuf,
+		  const void *writebuf,
+		  ULONGEST offset,
+		  LONGEST len)
+{
+  char *pathname;
+  int fd;
+  LONGEST n;
+
+  gdb_assert (object == TARGET_OBJECT_AUXV);
+  gdb_assert (readbuf || writebuf);
+
+  pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
+  fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
+  xfree (pathname);
+  if (fd < 0)
+    return -1;
+
+  if (offset != (ULONGEST) 0
+      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+    n = -1;
+  else if (readbuf != NULL)
+    n = read (fd, readbuf, len);
+  else
+    n = write (fd, writebuf, len);
+
+  (void) close (fd);
+
+  return n;
+}
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+   stored in *DATA.  Return the size in bytes of this data.
+   If zero, there is no data and *DATA is null.
+   if < 0, there was an error and *DATA is null.  */
+LONGEST
+target_auxv_read (struct target_ops *ops, char **data)
+{
+  size_t auxv_alloc = 512, auxv_pos = 0;
+  char *auxv = xmalloc (auxv_alloc);
+  int n;
+
+  while (1)
+    {
+      n = target_read_partial (ops, TARGET_OBJECT_AUXV,
+			       NULL, &auxv[auxv_pos], 0,
+			       auxv_alloc - auxv_pos);
+      if (n <= 0)
+	break;
+      auxv_pos += n;
+      if (auxv_pos < auxv_alloc) /* Read all there was.  */
+	break;
+      gdb_assert (auxv_pos == auxv_alloc);
+      auxv_alloc *= 2;
+      auxv = xrealloc (auxv, auxv_alloc);
+    }
+
+  if (auxv_pos == 0)
+    {
+      xfree (auxv);
+      *data = NULL;
+      return n;
+    }
+
+  *data = auxv;
+  return auxv_pos;
+}
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+   Return 0 if *READPTR is already at the end of the buffer.
+   Return -1 if there is insufficient buffer for a whole entry.
+   Return 1 if an entry was read into *TYPEP and *VALP.  */
+int
+target_auxv_parse (struct target_ops *ops, char **readptr, char *endptr,
+		   CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
+  char *ptr = *readptr;
+
+  if (endptr == ptr)
+    return 0;
+
+  if (endptr - ptr < sizeof_auxv_field * 2)
+    return -1;
+
+  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+
+  *readptr = ptr;
+  return 1;
+}
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+   Return zero if no such entry was found, or -1 if there was
+   an error getting the information.  On success, return 1 after
+   storing the entry's value field in *VALP.  */
+int
+target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
+{
+  CORE_ADDR type, val;
+  char *data;
+  int n = target_auxv_read (ops, &data);
+  char *ptr = data;
+  int ents = 0;
+
+  if (n <= 0)
+    return n;
+
+  while (1)
+    switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
+      {
+      case 1:			/* Here's an entry, check it.  */
+	if (type == match)
+	  {
+	    xfree (data);
+	    *valp = val;
+	    return 1;
+	  }
+	break;
+      case 0:			/* End of the vector.  */
+	xfree (data);
+	return 0;
+      default:			/* Bogosity.  */
+	xfree (data);
+	return -1;
+      }
+
+  /*NOTREACHED*/
+}
+
+
+/* Print the contents of the target's AUXV on the specified file. */
+int
+fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
+{
+  CORE_ADDR type, val;
+  char *data;
+  int len = target_auxv_read (ops, &data);
+  char *ptr = data;
+  int ents = 0;
+
+  if (len <= 0)
+    return len;
+
+  while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
+    {
+      extern int addressprint;
+      const char *name = "???";
+      const char *description = "";
+      enum { dec, hex, str } flavor = hex;
+
+      switch (type)
+	{
+#define TAG(tag, text, kind) \
+	case tag: name = #tag; description = text; flavor = kind; break
+	  TAG (AT_NULL, "End of vector", hex);
+	  TAG (AT_IGNORE, "Entry should be ignored", hex);
+	  TAG (AT_EXECFD, "File descriptor of program", dec);
+	  TAG (AT_PHDR, "Program headers for program", hex);
+	  TAG (AT_PHENT, "Size of program header entry", dec);
+	  TAG (AT_PHNUM, "Number of program headers", dec);
+	  TAG (AT_PAGESZ, "System page size", dec);
+	  TAG (AT_BASE, "Base address of interpreter", hex);
+	  TAG (AT_FLAGS, "Flags", hex);
+	  TAG (AT_ENTRY, "Entry point of program", hex);
+	  TAG (AT_NOTELF, "Program is not ELF", dec);
+	  TAG (AT_UID, "Real user ID", dec);
+	  TAG (AT_EUID, "Effective user ID", dec);
+	  TAG (AT_GID, "Real group ID", dec);
+	  TAG (AT_EGID, "Effective group ID", dec);
+	  TAG (AT_CLKTCK, "Frequency of times()", dec);
+	  TAG (AT_PLATFORM, "String identifying platform", str);
+	  TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex);
+	  TAG (AT_FPUCW, "Used FPU control word", dec);
+	  TAG (AT_DCACHEBSIZE, "Data cache block size", dec);
+	  TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec);
+	  TAG (AT_UCACHEBSIZE, "Unified cache block size", dec);
+	  TAG (AT_IGNOREPPC, "Entry should be ignored", dec);
+	  TAG (AT_SYSINFO, "Special system info/entry points", hex);
+	  TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex);
+	  TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec);
+	  TAG (AT_SUN_UID, "Effective user ID", dec);
+	  TAG (AT_SUN_RUID, "Real user ID", dec);
+	  TAG (AT_SUN_GID, "Effective group ID", dec);
+	  TAG (AT_SUN_RGID, "Real group ID", dec);
+	  TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex);
+	  TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex);
+	  TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str);
+	  TAG (AT_SUN_LPAGESZ, "Large pagesize", dec);
+	  TAG (AT_SUN_PLATFORM, "Platform name string", str);
+	  TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex);
+	  TAG (AT_SUN_IFLUSH, "Should flush icache?", dec);
+	  TAG (AT_SUN_CPU, "CPU name string", str);
+	  TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex);
+	  TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec);
+	  TAG (AT_SUN_EXECNAME,
+	       "Canonicalized file name given to execve", str);
+	  TAG (AT_SUN_MMU, "String for name of MMU module", str);
+	  TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex);
+	}
+
+      fprintf_filtered (file, "%-4s %-20s %-30s ",
+			paddr_d (type), name, description);
+      switch (flavor)
+	{
+	case dec:
+	  fprintf_filtered (file, "%s\n", paddr_d (val));
+	  break;
+	case hex:
+	  fprintf_filtered (file, "0x%s\n", paddr_nz (val));
+	  break;
+	case str:
+	  if (addressprint)
+	    fprintf_filtered (file, "0x%s", paddr_nz (val));
+	  val_print_string (val, -1, 1, file);
+	  fprintf_filtered (file, "\n");
+	  break;
+	}
+      ++ents;
+    }
+
+  xfree (data);
+
+  return ents;
+}
+
+static void
+info_auxv_command (char *cmd, int from_tty)
+{
+
+  if (! target_has_stack)
+    error ("The program has no auxiliary information now.");
+  else
+    {
+      int ents = fprint_target_auxv (gdb_stdout, &current_target);
+      if (ents < 0)
+	error ("No auxilary vector found, or failed reading it.");
+      else if (ents == 0)
+	error ("Auxilary vector is empty.");
+    }
+}
+
+
+extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
+
+void
+_initialize_auxv (void)
+{
+  add_info ("auxv", info_auxv_command,
+	    "Display the inferior's auxiliary vector.\n\
+This is information provided by the operating system at program startup.");
+}
Index: auxv.h
===================================================================
RCS file: auxv.h
diff -N auxv.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ auxv.h	29 Jan 2004 02:48:03 -0000
@@ -0,0 +1,75 @@
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef AUXV_H
+#define AUXV_H
+
+/* See "include/elf/common.h" for the definition of valid AT_* values.  */
+
+
+/* Avoid miscellaneous includes in this file, so that it can be
+   included by nm-*.h for the procfs_xfer_auxv decl if that is
+   used in NATIVE_XFER_AUXV.  */
+struct target_ops;		/* Forward declaration.  */
+
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+   stored in *DATA.  Return the size in bytes of this data.
+   If zero, there is no data and *DATA is null.
+   if < 0, there was an error and *DATA is null.  */
+extern LONGEST target_auxv_read (struct target_ops *ops, char **data);
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+   Return 0 if *READPTR is already at the end of the buffer.
+   Return -1 if there is insufficient buffer for a whole entry.
+   Return 1 if an entry was read into *TYPEP and *VALP.  */
+extern int target_auxv_parse (struct target_ops *ops,
+			      char **readptr, char *endptr,
+			      CORE_ADDR *typep, CORE_ADDR *valp);
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+   Return zero if no such entry was found, or -1 if there was
+   an error getting the information.  On success, return 1 after
+   storing the entry's value field in *VALP.  */
+extern int target_auxv_search (struct target_ops *ops,
+			       CORE_ADDR match, CORE_ADDR *valp);
+
+/* Print the contents of the target's AUXV on the specified file. */
+extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
+
+
+/* This function is called like a to_xfer_partial hook,
+   but must be called with TARGET_OBJECT_AUXV.
+   It handles access via /proc/PID/auxv, which is the common method.
+   This function is appropriate for doing:
+	   #define NATIVE_XFER_AUXV	procfs_xfer_auxv
+   for a native target that uses inftarg.c's child_xfer_partial hook.  */
+
+extern LONGEST procfs_xfer_auxv (struct target_ops *ops,
+				 int /* enum target_object */ object,
+				 const char *annex,
+				 void *readbuf,
+				 const void *writebuf,
+				 ULONGEST offset,
+				 LONGEST len);
+
+
+#endif
Index: sol-thread.c
===================================================================
RCS file: /cvs/src/src/gdb/sol-thread.c,v
retrieving revision 1.38
diff -b -p -u -r1.38 sol-thread.c
--- sol-thread.c	21 Sep 2003 01:26:45 -0000	1.38
+++ sol-thread.c	29 Jan 2004 02:44:52 -0000
@@ -750,6 +750,37 @@ sol_thread_xfer_memory (CORE_ADDR memadd
   return retval;
 }
 
+/* Perform partial transfers on OBJECT.  See target_read_partial
+   and target_write_partial for details of each variant.  One, and
+   only one, of readbuf or writebuf must be non-NULL.  */
+
+static LONGEST
+sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
+			  const char *annex, void *readbuf,
+			  const void *writebuf, ULONGEST offset, LONGEST len)
+{
+  int retval;
+  struct cleanup *old_chain;
+
+  old_chain = save_inferior_ptid ();
+
+  if (is_thread (inferior_ptid) ||	/* A thread */
+      !target_thread_alive (inferior_ptid))	/* An lwp, but not alive */
+    inferior_ptid = procfs_first_available ();	/* Find any live lwp.  */
+  /* Note: don't need to call switch_to_thread; we're just reading memory.  */
+
+  if (target_has_execution)
+    retval = procfs_ops.to_xfer_partial (ops, object, annex,
+					 readbuf, writebuf, offset, len);
+  else
+    retval = orig_core_ops.to_xfer_partial (ops, object, annex,
+					    readbuf, writebuf, offset, len);
+
+  do_cleanups (old_chain);
+
+  return retval;
+}
+
 /* Print status information about what we're accessing.  */
 
 static void
@@ -1549,6 +1580,7 @@ init_sol_thread_ops (void)
   sol_thread_ops.to_store_registers = sol_thread_store_registers;
   sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store;
   sol_thread_ops.to_xfer_memory = sol_thread_xfer_memory;
+  sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
   sol_thread_ops.to_files_info = sol_thread_files_info;
   sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
   sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
@@ -1592,6 +1624,7 @@ init_sol_core_ops (void)
   sol_core_ops.to_detach = sol_core_detach;
   sol_core_ops.to_fetch_registers = sol_thread_fetch_registers;
   sol_core_ops.to_xfer_memory = sol_thread_xfer_memory;
+  sol_core_ops.to_xfer_partial = sol_thread_xfer_partial;
   sol_core_ops.to_files_info = sol_core_files_info;
   sol_core_ops.to_insert_breakpoint = ignore;
   sol_core_ops.to_remove_breakpoint = ignore;
Index: procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/procfs.c,v
retrieving revision 1.50
diff -b -p -u -r1.50 procfs.c
--- procfs.c	17 Jan 2004 18:24:15 -0000	1.50
+++ procfs.c	29 Jan 2004 02:44:53 -0000
@@ -45,8 +45,10 @@ Inc., 59 Temple Place - Suite 330, Bosto
 #include "gdb_wait.h"
 #include <signal.h>
 #include <ctype.h>
+#include <string.h>
 #include "gdb_assert.h"
 #include "inflow.h"
+#include "auxv.h"
 
 /* 
  * PROCFS.C
@@ -127,6 +129,11 @@ static ptid_t procfs_wait (ptid_t, struc
 static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
 			       struct mem_attrib *attrib,
 			       struct target_ops *);
+static LONGEST procfs_xfer_partial (struct target_ops *ops,
+				    enum target_object object,
+				    const char *annex,
+				    void *readbuf, const void *writebuf,
+				    ULONGEST offset, LONGEST len);
 
 static int procfs_thread_alive (ptid_t);
 
@@ -164,6 +171,7 @@ init_procfs_ops (void)
   procfs_ops.to_prepare_to_store    = procfs_prepare_to_store;
   procfs_ops.to_fetch_registers     = procfs_fetch_registers;
   procfs_ops.to_store_registers     = procfs_store_registers;
+  procfs_ops.to_xfer_partial        = procfs_xfer_partial;
   procfs_ops.to_xfer_memory         = procfs_xfer_memory;
   procfs_ops.to_insert_breakpoint   =  memory_insert_breakpoint;
   procfs_ops.to_remove_breakpoint   =  memory_remove_breakpoint;
@@ -4267,6 +4275,40 @@ wait_again:
   return retval;
 }
 
+/* Perform a partial transfer to/from the specified object.  For
+   memory transfers, fall back to the old memory xfer functions.  */
+
+static LONGEST
+procfs_xfer_partial (struct target_ops *ops, enum target_object object,
+		     const char *annex, void *readbuf,
+		     const void *writebuf, ULONGEST offset, LONGEST len)
+{
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+	return (*ops->to_xfer_memory) (offset, readbuf, len, 0/*write*/,
+				       NULL, ops);
+      if (writebuf)
+	return (*ops->to_xfer_memory) (offset, readbuf, len, 1/*write*/,
+				       NULL, ops);
+      return -1;
+
+#ifdef NEW_PROC_API
+    case TARGET_OBJECT_AUXV:
+      return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
+			       offset, len);
+#endif
+
+    default:
+      if (ops->beneath != NULL)
+	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					      readbuf, writebuf, offset, len);
+      return -1;
+    }
+}
+
+
 /* Transfer LEN bytes between GDB address MYADDR and target address
    MEMADDR.  If DOWRITE is non-zero, transfer them to the target,
    otherwise transfer them from the target.  TARGET is unused.
@@ -5849,6 +5891,8 @@ procfs_make_note_section (bfd *obfd, int
   char *note_data = NULL;
   char *inf_args;
   struct procfs_corefile_thread_data thread_args;
+  char *auxv;
+  int auxv_len;
 
   if (get_exec_file (0))
     {
@@ -5895,6 +5939,14 @@ procfs_make_note_section (bfd *obfd, int
   else
     {
       note_data = thread_args.note_data;
+    }
+
+  auxv_len = target_auxv_read (&current_target, &auxv);
+  if (auxv_len > 0)
+    {
+      note_data = elfcore_write_note (obfd, note_data, note_size,
+				      "CORE", NT_AUXV, auxv, auxv_len);
+      xfree (auxv);
     }
 
   make_cleanup (xfree, note_data);
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	29 Jan 2004 02:44:53 -0000
@@ -271,6 +271,8 @@ linux_make_note_section (bfd *obfd, int 
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
+  char *auxv;
+  int auxv_len;
 
   if (get_exec_file (0))
     {
@@ -305,6 +307,14 @@ linux_make_note_section (bfd *obfd, int 
       note_data = thread_args.note_data;
     }
 
+  auxv_len = target_auxv_read (&current_target, &auxv);
+  if (auxv_len > 0)
+    {
+      note_data = elfcore_write_note (obfd, note_data, note_size,
+				      "CORE", NT_AUXV, auxv, auxv_len);
+      xfree (auxv);
+    }
+
   make_cleanup (xfree, note_data);
   return note_data;
 }
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.482
diff -b -p -u -r1.482 Makefile.in
--- Makefile.in	25 Jan 2004 11:46:44 -0000	1.482
+++ Makefile.in	29 Jan 2004 02:44:53 -0000
@@ -652,6 +652,7 @@ amd64_nat_h = amd64-nat.h
 annotate_h = annotate.h $(symtab_h) $(gdbtypes_h)
 arch_utils_h = arch-utils.h
 arm_tdep_h = arm-tdep.h
+auxv_h = auxv.h
 ax_gdb_h = ax-gdb.h
 ax_h = ax.h $(doublest_h)
 bcache_h = bcache.h
@@ -891,6 +892,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_
 TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
 
 COMMON_OBS = version.o \
+	auxv.o \
 	bfd-target.o \
 	blockframe.o breakpoint.o findvar.o regcache.o \
 	charset.o disasm.o dummy-frame.o \
@@ -1621,6 +1624,8 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame
 	$(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(arm_tdep_h) \
 	$(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \
 	$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h)
+auxv.o: $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) $(gdb_assert_h) \
+	$(auxv_h) $(elf_common_h) $(valprint_h) $(inferior_h)
 avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
 	$(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(symfile_h) $(arch_utils_h) $(regcache_h) \
@@ -2180,7 +2187,7 @@ proc-flags.o: proc-flags.c $(defs_h)
 procfs.o: procfs.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
 	$(elf_bfd_h) $(gdbcmd_h) $(gdbthread_h) $(gdb_wait_h) \
 	$(gdb_assert_h) $(inflow_h) $(gdb_dirent_h) $(X_OK) $(gdb_stat_h) \
-	$(proc_utils_h) $(gregset_h)
+	$(proc_utils_h) $(gregset_h) $(auxv_h)
 proc-service.o: proc-service.c $(defs_h) $(gdb_proc_service_h) $(inferior_h) \
 	$(symtab_h) $(target_h) $(gregset_h)
 proc-why.o: proc-why.c $(defs_h) $(proc_utils_h)
cvs server: I know nothing about auxv.c
cvs server: I know nothing about auxv.h
Index: corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.33
diff -b -p -u -r1.33 corelow.c
--- corelow.c	6 Nov 2003 02:52:27 -0000	1.33
+++ corelow.c	29 Jan 2004 02:44:53 -0000
@@ -515,6 +515,63 @@ core_files_info (struct target_ops *t)
   print_section_info (t, core_bfd);
 }
 
+static LONGEST
+core_xfer_partial (struct target_ops *ops, enum target_object object,
+		   const char *annex, void *readbuf,
+		   const void *writebuf, ULONGEST offset, LONGEST len)
+{
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+	return (*ops->to_xfer_memory) (offset, readbuf, len, 0/*write*/,
+				       NULL, ops);
+      if (writebuf)
+	return (*ops->to_xfer_memory) (offset, readbuf, len, 1/*write*/,
+				       NULL, ops);
+      return -1;
+
+    case TARGET_OBJECT_AUXV:
+      if (readbuf)
+	{
+	  /* When the aux vector is stored in core file, BFD
+	     represents this with a fake section called ".auxv".  */
+
+	  sec_ptr section;
+	  bfd_size_type size;
+	  char *contents;
+
+	  section = bfd_get_section_by_name (core_bfd, ".auxv");
+	  if (section == NULL)
+	    return -1;
+
+	  size = bfd_section_size (core_bfd, section);
+	  if (offset >= size)
+	    return 0;
+	  size -= offset;
+	  if (size > len)
+	    size = len;
+	  if (size > 0 &&
+	      ! bfd_get_section_contents (core_bfd, section, readbuf,
+					  (file_ptr) offset, size))
+	    {
+	      warning ("Couldn't read NT_AUXV note in core file.");
+	      return -1;
+	    }
+
+	  return size;
+	}
+      return -1;
+
+    default:
+      if (ops->beneath != NULL)
+	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					      readbuf, writebuf, offset, len);
+      return -1;
+    }
+}
+
+
 /* If mourn is being called in all the right places, this could be say
    `gdb internal error' (since generic_mourn calls breakpoint_init_inferior).  */
 
@@ -551,6 +608,7 @@ init_core_ops (void)
   core_ops.to_attach = find_default_attach;
   core_ops.to_detach = core_detach;
   core_ops.to_fetch_registers = get_core_registers;
+  core_ops.to_xfer_partial = core_xfer_partial;
   core_ops.to_xfer_memory = xfer_memory;
   core_ops.to_files_info = core_files_info;
   core_ops.to_insert_breakpoint = ignore;
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.55
diff -b -p -u -r1.55 target.h
--- target.h	17 Jan 2004 21:56:12 -0000	1.55
+++ target.h	29 Jan 2004 02:44:53 -0000
@@ -226,8 +226,10 @@ enum target_object
   TARGET_OBJECT_MEMORY,
   /* Kernel Unwind Table.  See "ia64-tdep.c".  */
   TARGET_OBJECT_UNWIND_TABLE,
-  /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC,
-     TARGET_OBJECT_AUXV, ...  */
+  /* Transfer auxilliary vector.  */
+  TARGET_OBJECT_AUXV,
+
+  /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
 };
 
 extern LONGEST target_read_partial (struct target_ops *ops,
Index: inftarg.c
===================================================================
RCS file: /cvs/src/src/gdb/inftarg.c,v
retrieving revision 1.21
diff -b -p -u -r1.21 inftarg.c
--- inftarg.c	14 Nov 2003 20:49:23 -0000	1.21
+++ inftarg.c	29 Jan 2004 02:44:53 -0000
@@ -578,11 +578,12 @@ child_xfer_partial (struct target_ops *o
       return NATIVE_XFER_UNWIND_TABLE (ops, object, annex, readbuf, writebuf,
 				       offset, len);
 
-#if 0
     case TARGET_OBJECT_AUXV:
-      return native_xfer_auxv (PIDGET (inferior_ptid), readbuf, writebuf,
-			       offset, len);
+#ifndef NATIVE_XFER_AUXV
+#define NATIVE_XFER_AUXV(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
 #endif
+      return NATIVE_XFER_AUXV (ops, object, annex, readbuf, writebuf,
+			       offset, len);
 
     default:
       return -1;
Index: config/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/nm-linux.h,v
retrieving revision 1.19
diff -b -p -u -r1.19 nm-linux.h
--- config/nm-linux.h	17 Aug 2003 18:22:25 -0000	1.19
+++ config/nm-linux.h	29 Jan 2004 02:44:53 -0000
@@ -77,3 +77,6 @@ extern void lin_thread_get_thread_signal
 #define CHILD_POST_ATTACH
 #define CHILD_FOLLOW_FORK
 #define KILL_INFERIOR
+
+#define NATIVE_XFER_AUXV	procfs_xfer_auxv
+#include "auxv.h"		/* Declares it. */


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