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]

Re: [RFC/commit] ppc-aix core file relocation.


Hi Pedro,

> Thanks!  This is definitely the way to go.

My pleasure :).

> > +   If CLOSE_LDINFO_FD is nonzero, then this routine also closes
> > +   the ldinfo_fd file descriptor.  This is useful when the ldinfo
> > +   data is obtained via ptrace, as ptrace opens a file descriptor
> > +   for each and every entry; but we cannot use this descriptor
> > +   as the consumer of the XML library list might live in a different
> > +   process.  */
> 
> How interesting.  So AIX's list is better than glibc in that we
> could use that descriptor to avoid the "library file gdb opens is
> no longer the same as the inferior opened" issue.

True. Now, if only we could send the "fd" across processes :-).

> > +struct ld_info
> > +{
> > +  int next;
> 
> I'm surprised this is signed.
> It was unsigned on Ulrich's version: http://sourceware.org/ml/gdb-patches/2007-05/msg00321.html

Right you are. I read sys/ldr.h pretty carefully, and was convinced
that they had defined it as an int, but not so. For the record:

 ==============================================================================
 | Field Name      | __ld_info32 size;type(s)| __ld_info64 size; type(s)      |
 |============================================================================|
 | ldinfo_next     | 4; uint                 | 4; uint                        |
 | ldinfo_flags    | n/a                     | 4; uint                        |
 | ldinfo_fd       | 4; int                  | 4; int                         |
 | ldinfo_fp       | 4; struct file * / uint | 4; struct file *      / uint   |
 | ldinfo_core     | 4; int           / int  | 8; long long          / long   |
 | ldinfo_textorg  | 4; void *        / uint | 8; unsigned long long / void * |
 | ldinfo_textsize | 4; int                  | 8; long long          / long   |
 | ldinfo_dataorg  | 4; void *        / uint | 8; unsigned long long / void * |
 | ldinfo_datasize | 4; int                  | 8; long long          / long   |
 | ldinfo_filename | variable                | variable                       |
 ==============================================================================

> Anyway, I skimmed it and it looked good to me.

Thanks! I made the following adjustments to my patch making "next"
unsigned...

| diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
| index 450abae..9956eb3 100644
| --- a/gdb/rs6000-aix-tdep.c
| +++ b/gdb/rs6000-aix-tdep.c
| @@ -854,7 +854,7 @@ static const struct ld_info_desc ld_info64_desc =
|  
|  struct ld_info
|  {
| -  int next;
| +  ULONGEST next;
|    int fd;
|    CORE_ADDR textorg;
|    ULONGEST textsize;
| @@ -882,9 +882,9 @@ rs6000_aix_extract_ld_info (struct gdbarch *gdbarch,
|      = tdep->wordsize == 8 ? ld_info64_desc : ld_info32_desc;
|    struct ld_info info;
|  
| -  info.next = extract_signed_integer (ldi_buf + desc.ldinfo_next.offset,
| -				      desc.ldinfo_next.size,
| -				      byte_order);
| +  info.next = extract_unsigned_integer (ldi_buf + desc.ldinfo_next.offset,
| +					desc.ldinfo_next.size,
| +					byte_order);
|    info.fd = extract_signed_integer (ldi_buf + desc.ldinfo_fd.offset,
|  				    desc.ldinfo_fd.size,
|  				    byte_order);

... and checked the patch in.

For the record, attached is the patch I checked in.

Thanks for the quick review!
-- 
Joel
>From 88207bfef87419b23851ebd2c32004ff63fdb35c Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Wed, 15 May 2013 11:24:43 +0200
Subject: [PATCH] ppc-aix core file relocation.

The current code attempts to provide relocation support when debugging
core files via the rs6000_xfer_partial method of the rs6000-nat
target_ops vector. However, this target_ops vector does not get pushed
on the target stack at all when debugging core files, thus bypassing
completely that part of the code.

This patch fixes the problem by extending corelow's core_xfer_partial
into handling the TARGET_OBJECT_LIBRARIES_AIX object.

gdb/ChangeLog:

	* gdbarch.sh (core_xfer_shared_libraries_aix): New method.
	* gdbarch.h, gdbarch.c: Regenerate.
	* corelow.c (core_xfer_partial): Add TARGET_OBJECT_LIBRARIES_AIX
	handling.

	* rs6000-aix-tdep.h: New file.
	* Makefile.in (HFILES_NO_SRCDIR): Add rs6000-aix-tdep.h.
	* rs6000-aix-tdep.c: Include "rs6000-aix-tdep.h" and
	"xml-utils.h".
	(struct field_info, struct ld_info_desc): New types.
	(ld_info32_desc, ld_info64_desc): New static constants.
	(struct ld_info): New type.
	(rs6000_aix_extract_ld_info): New function.
	(rs6000_aix_shared_library_to_xml): Likewise.
	(rs6000_aix_ld_info_to_xml): Likewise.
	(rs6000_aix_core_xfer_shared_libraries_aix): Likewise.
	(rs6000_aix_init_osabi): Add call to
	set_gdbarch_core_xfer_shared_libraries_aix.
	* rs6000-nat.c: Add "rs6000-aix-tdep.h" include.
	Remove "xml-utils.h" include.
	(LdInfo): Delete typedef.
	(ARCH64_DECL, LDI_FIELD, LDI_NEXT, LDI_FD, LDI_FILENAME):
	Delete macros.
	(rs6000_ptrace_ldinfo): Change return type to gdb_byte *.
	Adjust code accordingly.
	(rs6000_core_ldinfo): Delete, folded into
	rs6000_aix_core_xfer_shared_libraries_aix.
	(rs6000_xfer_shared_library): Delete.
	(rs6000_xfer_shared_libraries): Reimplement.
---
 gdb/Makefile.in       |    3 +-
 gdb/corelow.c         |   12 ++
 gdb/gdbarch.c         |   33 ++++++
 gdb/gdbarch.h         |    9 ++
 gdb/gdbarch.sh        |    4 +
 gdb/rs6000-aix-tdep.c |  297 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/rs6000-aix-tdep.h |   28 +++++
 gdb/rs6000-nat.c      |  210 +++-------------------------------
 8 files changed, 403 insertions(+), 193 deletions(-)
 create mode 100644 gdb/rs6000-aix-tdep.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 08ebaae..1f35432 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -824,7 +824,8 @@ amd64-linux-tdep.h linespec.h i387-tdep.h mn10300-tdep.h \
 sparc64-tdep.h monitor.h ppcobsd-tdep.h srec.h solib-pa64.h \
 coff-pe-read.h parser-defs.h gdb_ptrace.h mips-linux-tdep.h \
 m68k-tdep.h spu-tdep.h jv-lang.h environ.h solib-irix.h amd64-tdep.h \
-doublest.h regset.h hppa-tdep.h ppc-linux-tdep.h ppc64-tdep.h rs6000-tdep.h \
+doublest.h regset.h hppa-tdep.h ppc-linux-tdep.h ppc64-tdep.h \
+rs6000-tdep.h rs6000-aix-tdep.h \
 common/gdb_locale.h common/gdb_dirent.h arch-utils.h trad-frame.h gnu-nat.h \
 language.h nbsd-tdep.h solib-svr4.h \
 macroexp.h ui-file.h regcache.h tracepoint.h i386-tdep.h \
diff --git a/gdb/corelow.c b/gdb/corelow.c
index de940fc..0bfa743 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -756,6 +756,18 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
 	}
       /* FALL THROUGH */
 
+    case TARGET_OBJECT_LIBRARIES_AIX:
+      if (core_gdbarch
+	  && gdbarch_core_xfer_shared_libraries_aix_p (core_gdbarch))
+	{
+	  if (writebuf)
+	    return -1;
+	  return
+	    gdbarch_core_xfer_shared_libraries_aix (core_gdbarch,
+						    readbuf, offset, len);
+	}
+      /* FALL THROUGH */
+
     case TARGET_OBJECT_SPU:
       if (readbuf && annex)
 	{
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index b97a894..a09b374 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -242,6 +242,7 @@ struct gdbarch
   gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo;
   gdbarch_find_memory_regions_ftype *find_memory_regions;
   gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
+  gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix;
   gdbarch_core_pid_to_str_ftype *core_pid_to_str;
   const char * gcore_bfd_target;
   int vtable_function_descriptors;
@@ -414,6 +415,7 @@ struct gdbarch startup_gdbarch =
   0,  /* elfcore_write_linux_prpsinfo */
   0,  /* find_memory_regions */
   0,  /* core_xfer_shared_libraries */
+  0,  /* core_xfer_shared_libraries_aix */
   0,  /* core_pid_to_str */
   0,  /* gcore_bfd_target */
   0,  /* vtable_function_descriptors */
@@ -718,6 +720,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of elfcore_write_linux_prpsinfo, has predicate.  */
   /* Skip verify of find_memory_regions, has predicate.  */
   /* Skip verify of core_xfer_shared_libraries, has predicate.  */
+  /* Skip verify of core_xfer_shared_libraries_aix, has predicate.  */
   /* Skip verify of core_pid_to_str, has predicate.  */
   /* Skip verify of gcore_bfd_target, has predicate.  */
   /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
@@ -908,6 +911,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: core_xfer_shared_libraries = <%s>\n",
                       host_address_to_string (gdbarch->core_xfer_shared_libraries));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_core_xfer_shared_libraries_aix_p() = %d\n",
+                      gdbarch_core_xfer_shared_libraries_aix_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: core_xfer_shared_libraries_aix = <%s>\n",
+                      host_address_to_string (gdbarch->core_xfer_shared_libraries_aix));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: decr_pc_after_break = %s\n",
                       core_addr_to_string_nz (gdbarch->decr_pc_after_break));
   fprintf_unfiltered (file,
@@ -3473,6 +3482,30 @@ set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->core_xfer_shared_libraries_aix != NULL;
+}
+
+LONGEST
+gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->core_xfer_shared_libraries_aix != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_core_xfer_shared_libraries_aix called\n");
+  return gdbarch->core_xfer_shared_libraries_aix (gdbarch, readbuf, offset, len);
+}
+
+void
+set_gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch,
+                                            gdbarch_core_xfer_shared_libraries_aix_ftype core_xfer_shared_libraries_aix)
+{
+  gdbarch->core_xfer_shared_libraries_aix = core_xfer_shared_libraries_aix;
+}
+
+int
 gdbarch_core_pid_to_str_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index e01ce92..aa67a14 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -773,6 +773,15 @@ typedef LONGEST (gdbarch_core_xfer_shared_libraries_ftype) (struct gdbarch *gdba
 extern LONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len);
 extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries);
 
+/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES_AIX formatted shared
+   libraries list from core file into buffer READBUF with length LEN. */
+
+extern int gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch);
+
+typedef LONGEST (gdbarch_core_xfer_shared_libraries_aix_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len);
+extern LONGEST gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len);
+extern void set_gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix);
+
 /* How the core target converts a PTID from a core file to a string. */
 
 extern int gdbarch_core_pid_to_str_p (struct gdbarch *gdbarch);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 6503eae..6479846 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -659,6 +659,10 @@ M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data
 # core file into buffer READBUF with length LEN.
 M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
 
+# Read offset OFFSET of TARGET_OBJECT_LIBRARIES_AIX formatted shared
+# libraries list from core file into buffer READBUF with length LEN.
+M:LONGEST:core_xfer_shared_libraries_aix:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
+
 # How the core target converts a PTID from a core file to a string.
 M:char *:core_pid_to_str:ptid_t ptid:ptid
 
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index 0d4fec5..9956eb3 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -34,10 +34,12 @@
 #include "breakpoint.h"
 #include "rs6000-tdep.h"
 #include "ppc-tdep.h"
+#include "rs6000-aix-tdep.h"
 #include "exceptions.h"
 #include "xcoffread.h"
 #include "solib.h"
 #include "solib-aix.h"
+#include "xml-utils.h"
 
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
@@ -747,6 +749,299 @@ rs6000_aix_osabi_sniffer (bfd *abfd)
   return GDB_OSABI_AIX;
 }
 
+/* A structure encoding the offset and size of a field within
+   a struct.  */
+
+struct field_info
+{
+  int offset;
+  int size;
+};
+
+/* A structure describing the layout of all the fields of interest
+   in AIX's struct ld_info.  Each field in this struct corresponds
+   to the field of the same name in struct ld_info.  */
+
+struct ld_info_desc
+{
+  struct field_info ldinfo_next;
+  struct field_info ldinfo_fd;
+  struct field_info ldinfo_textorg;
+  struct field_info ldinfo_textsize;
+  struct field_info ldinfo_dataorg;
+  struct field_info ldinfo_datasize;
+  struct field_info ldinfo_filename;
+};
+
+/* The following data has been generated by compiling and running
+   the following program on AIX 5.3.  */
+
+#if 0
+    #include <stddef.h>
+    #include <stdio.h>
+    #define __LDINFO_PTRACE32__
+    #define __LDINFO_PTRACE64__
+    #include <sys/ldr.h>
+
+    #define pinfo(type,member)              \
+      {                                         \
+        struct type ldi = {0};                  \
+                                                \
+        printf ("  {%d, %d},\t/* %s */\n",      \
+                offsetof (struct type, member), \
+                sizeof (ldi.member),            \
+                #member);                       \
+      }                                         \
+      while (0)
+
+    int
+    main (void)
+    {
+      printf ("static const struct ld_info_desc ld_info32_desc =\n{\n");
+      pinfo (__ld_info32, ldinfo_next);
+      pinfo (__ld_info32, ldinfo_fd);
+      pinfo (__ld_info32, ldinfo_textorg);
+      pinfo (__ld_info32, ldinfo_textsize);
+      pinfo (__ld_info32, ldinfo_dataorg);
+      pinfo (__ld_info32, ldinfo_datasize);
+      pinfo (__ld_info32, ldinfo_filename);
+      printf ("};\n");
+
+      printf ("\n");
+
+      printf ("static const struct ld_info_desc ld_info64_desc =\n{\n");
+      pinfo (__ld_info64, ldinfo_next);
+      pinfo (__ld_info64, ldinfo_fd);
+      pinfo (__ld_info64, ldinfo_textorg);
+      pinfo (__ld_info64, ldinfo_textsize);
+      pinfo (__ld_info64, ldinfo_dataorg);
+      pinfo (__ld_info64, ldinfo_datasize);
+      pinfo (__ld_info64, ldinfo_filename);
+      printf ("};\n");
+
+      return 0;
+    }
+#endif /* 0 */
+
+/* Layout of the 32bit version of struct ld_info.  */
+
+static const struct ld_info_desc ld_info32_desc =
+{
+  {0, 4},       /* ldinfo_next */
+  {4, 4},       /* ldinfo_fd */
+  {8, 4},       /* ldinfo_textorg */
+  {12, 4},      /* ldinfo_textsize */
+  {16, 4},      /* ldinfo_dataorg */
+  {20, 4},      /* ldinfo_datasize */
+  {24, 2},      /* ldinfo_filename */
+};
+
+/* Layout of the 64bit version of struct ld_info.  */
+
+static const struct ld_info_desc ld_info64_desc =
+{
+  {0, 4},       /* ldinfo_next */
+  {8, 4},       /* ldinfo_fd */
+  {16, 8},      /* ldinfo_textorg */
+  {24, 8},      /* ldinfo_textsize */
+  {32, 8},      /* ldinfo_dataorg */
+  {40, 8},      /* ldinfo_datasize */
+  {48, 2},      /* ldinfo_filename */
+};
+
+/* A structured representation of one entry read from the ld_info
+   binary data provided by the AIX loader.  */
+
+struct ld_info
+{
+  ULONGEST next;
+  int fd;
+  CORE_ADDR textorg;
+  ULONGEST textsize;
+  CORE_ADDR dataorg;
+  ULONGEST datasize;
+  char *filename;
+  char *member_name;
+};
+
+/* Return a struct ld_info object corresponding to the entry at
+   LDI_BUF.
+
+   Note that the filename and member_name strings still point
+   to the data in LDI_BUF.  So LDI_BUF must not be deallocated
+   while the struct ld_info object returned is in use.  */
+
+static struct ld_info
+rs6000_aix_extract_ld_info (struct gdbarch *gdbarch,
+			    const gdb_byte *ldi_buf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  const struct ld_info_desc desc
+    = tdep->wordsize == 8 ? ld_info64_desc : ld_info32_desc;
+  struct ld_info info;
+
+  info.next = extract_unsigned_integer (ldi_buf + desc.ldinfo_next.offset,
+					desc.ldinfo_next.size,
+					byte_order);
+  info.fd = extract_signed_integer (ldi_buf + desc.ldinfo_fd.offset,
+				    desc.ldinfo_fd.size,
+				    byte_order);
+  info.textorg = extract_typed_address (ldi_buf + desc.ldinfo_textorg.offset,
+					ptr_type);
+  info.textsize
+    = extract_unsigned_integer (ldi_buf + desc.ldinfo_textsize.offset,
+				desc.ldinfo_textsize.size,
+				byte_order);
+  info.dataorg = extract_typed_address (ldi_buf + desc.ldinfo_dataorg.offset,
+					ptr_type);
+  info.datasize
+    = extract_unsigned_integer (ldi_buf + desc.ldinfo_datasize.offset,
+				desc.ldinfo_datasize.size,
+				byte_order);
+  info.filename = (char *) ldi_buf + desc.ldinfo_filename.offset;
+  info.member_name = info.filename + strlen (info.filename) + 1;
+
+  return info;
+}
+
+/* Append to OBJSTACK an XML string description of the shared library
+   corresponding to LDI, following the TARGET_OBJECT_LIBRARIES_AIX
+   format.  */
+
+static void
+rs6000_aix_shared_library_to_xml (struct ld_info *ldi,
+				  struct obstack *obstack)
+{
+  char *p;
+
+  obstack_grow_str (obstack, "<library name=\"");
+  p = xml_escape_text (ldi->filename);
+  obstack_grow_str (obstack, p);
+  xfree (p);
+  obstack_grow_str (obstack, "\"");
+
+  if (ldi->member_name[0] != '\0')
+    {
+      obstack_grow_str (obstack, " member=\"");
+      p = xml_escape_text (ldi->member_name);
+      obstack_grow_str (obstack, p);
+      xfree (p);
+      obstack_grow_str (obstack, "\"");
+    }
+
+  obstack_grow_str (obstack, " text_addr=\"");
+  obstack_grow_str (obstack, core_addr_to_string (ldi->textorg));
+  obstack_grow_str (obstack, "\"");
+
+  obstack_grow_str (obstack, " text_size=\"");
+  obstack_grow_str (obstack, pulongest (ldi->textsize));
+  obstack_grow_str (obstack, "\"");
+
+  obstack_grow_str (obstack, " data_addr=\"");
+  obstack_grow_str (obstack, core_addr_to_string (ldi->dataorg));
+  obstack_grow_str (obstack, "\"");
+
+  obstack_grow_str (obstack, " data_size=\"");
+  obstack_grow_str (obstack, pulongest (ldi->datasize));
+  obstack_grow_str (obstack, "\"");
+
+  obstack_grow_str (obstack, "></library>");
+}
+
+/* Convert the ld_info binary data provided by the AIX loader into
+   an XML representation following the TARGET_OBJECT_LIBRARIES_AIX
+   format.
+
+   LDI_BUF is a buffer containing the ld_info data.
+   READBUF, OFFSET and LEN follow the same semantics as target_ops'
+   to_xfer_partial target_ops method.
+
+   If CLOSE_LDINFO_FD is nonzero, then this routine also closes
+   the ldinfo_fd file descriptor.  This is useful when the ldinfo
+   data is obtained via ptrace, as ptrace opens a file descriptor
+   for each and every entry; but we cannot use this descriptor
+   as the consumer of the XML library list might live in a different
+   process.  */
+
+LONGEST
+rs6000_aix_ld_info_to_xml (struct gdbarch *gdbarch, const gdb_byte *ldi_buf,
+			   gdb_byte *readbuf, ULONGEST offset, LONGEST len,
+			   int close_ldinfo_fd)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list-aix version=\"1.0\">\n");
+
+  while (1)
+    {
+      struct ld_info ldi = rs6000_aix_extract_ld_info (gdbarch, ldi_buf);
+
+      rs6000_aix_shared_library_to_xml (&ldi, &obstack);
+      if (close_ldinfo_fd)
+	close (ldi.fd);
+
+      if (!ldi.next)
+	break;
+      ldi_buf = ldi_buf + ldi.next;
+    }
+
+  obstack_grow_str0 (&obstack, "</library-list-aix>\n");
+
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    len= 0;
+  else
+    {
+      if (len > len_avail - offset)
+        len = len_avail - offset;
+      memcpy (readbuf, buf + offset, len);
+    }
+
+  obstack_free (&obstack, NULL);
+  return len;
+}
+
+/* Implement the core_xfer_shared_libraries_aix gdbarch method.  */
+
+static LONGEST
+rs6000_aix_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch,
+					   gdb_byte *readbuf,
+					   ULONGEST offset,
+					   LONGEST len)
+{
+  struct bfd_section *ldinfo_sec;
+  int ldinfo_size;
+  gdb_byte *ldinfo_buf;
+  struct cleanup *cleanup;
+  LONGEST result;
+
+  ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo");
+  if (ldinfo_sec == NULL)
+    error (_("cannot find .ldinfo section from core file: %s"),
+	   bfd_errmsg (bfd_get_error ()));
+  ldinfo_size = bfd_get_section_size (ldinfo_sec);
+
+  ldinfo_buf = xmalloc (ldinfo_size);
+  cleanup = make_cleanup (xfree, ldinfo_buf);
+
+  if (! bfd_get_section_contents (core_bfd, ldinfo_sec,
+				  ldinfo_buf, 0, ldinfo_size))
+    error (_("unable to read .ldinfo section from core file: %s"),
+	  bfd_errmsg (bfd_get_error ()));
+
+  result = rs6000_aix_ld_info_to_xml (gdbarch, ldinfo_buf, readbuf,
+				      offset, len, 0);
+
+  do_cleanups (cleanup);
+  return result;
+}
+
 static void
 rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -774,6 +1069,8 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Core file support.  */
   set_gdbarch_regset_from_core_section
     (gdbarch, rs6000_aix_regset_from_core_section);
+  set_gdbarch_core_xfer_shared_libraries_aix
+    (gdbarch, rs6000_aix_core_xfer_shared_libraries_aix);
 
   if (tdep->wordsize == 8)
     tdep->lr_frame_offset = 16;
diff --git a/gdb/rs6000-aix-tdep.h b/gdb/rs6000-aix-tdep.h
new file mode 100644
index 0000000..07c37f5
--- /dev/null
+++ b/gdb/rs6000-aix-tdep.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2013 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef RS6000_AIX_TDEP_H
+#define RS6000_AIX_TDEP_H
+
+extern LONGEST rs6000_aix_ld_info_to_xml (struct gdbarch *gdbarch,
+					  const gdb_byte *ldi_buf,
+					  gdb_byte *readbuf,
+					  ULONGEST offset,
+					  LONGEST len,
+					  int close_ldinfo_fd);
+
+#endif /* RS6000_AIX_TDEP_H */
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index 1af8610..1b600f0 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -33,6 +33,7 @@
 #include "inf-ptrace.h"
 #include "ppc-tdep.h"
 #include "rs6000-tdep.h"
+#include "rs6000-aix-tdep.h"
 #include "exec.h"
 #include "observer.h"
 #include "xcoffread.h"
@@ -57,7 +58,6 @@
 #define __LDINFO_PTRACE64__	/* for __ld_info64 */
 #include <sys/ldr.h>
 #include <sys/systemcfg.h>
-#include "xml-utils.h"
 
 /* On AIX4.3+, sys/ldr.h provides different versions of struct ld_info for
    debugging 32-bit and 64-bit processes.  Define a typedef and macros for
@@ -78,46 +78,6 @@
 # define ARCH64() (register_size (target_gdbarch (), 0) == 8)
 #endif
 
-/* Union of 32-bit and 64-bit versions of ld_info.  */
-
-typedef union {
-#ifndef ARCH3264
-  struct ld_info l32;
-  struct ld_info l64;
-#else
-  struct __ld_info32 l32;
-  struct __ld_info64 l64;
-#endif
-} LdInfo;
-
-/* If compiling with 32-bit and 64-bit debugging capability (e.g. AIX 4.x),
-   declare and initialize a variable named VAR suitable for use as the arch64
-   parameter to the various LDI_*() macros.  */
-
-#ifndef ARCH3264
-# define ARCH64_DECL(var)
-#else
-# define ARCH64_DECL(var) int var = ARCH64 ()
-#endif
-
-/* Return LDI's FIELD for a 64-bit process if ARCH64 and for a 32-bit process
-   otherwise.  This technique only works for FIELDs with the same data type in
-   32-bit and 64-bit versions of ld_info.  */
-
-#ifndef ARCH3264
-# define LDI_FIELD(ldi, arch64, field) (ldi)->l32.ldinfo_##field
-#else
-# define LDI_FIELD(ldi, arch64, field) \
-  (arch64 ? (ldi)->l64.ldinfo_##field : (ldi)->l32.ldinfo_##field)
-#endif
-
-/* Return various LDI fields for a 64-bit process if ARCH64 and for a 32-bit
-   process otherwise.  */
-
-#define LDI_NEXT(ldi, arch64)		LDI_FIELD(ldi, arch64, next)
-#define LDI_FD(ldi, arch64)		LDI_FIELD(ldi, arch64, fd)
-#define LDI_FILENAME(ldi, arch64)	LDI_FIELD(ldi, arch64, filename)
-
 static void exec_one_dummy_insn (struct regcache *);
 
 static LONGEST rs6000_xfer_shared_libraries
@@ -682,12 +642,12 @@ rs6000_create_inferior (struct target_ops * ops, char *exec_file,
 
    The returned value must be deallocated after use.  */
 
-static LdInfo *
+static gdb_byte *
 rs6000_ptrace_ldinfo (ptid_t ptid)
 {
   const int pid = ptid_get_pid (ptid);
   int ldi_size = 1024;
-  LdInfo *ldi = xmalloc (ldi_size);
+  gdb_byte *ldi = xmalloc (ldi_size);
   int rc = -1;
 
   while (1)
@@ -712,104 +672,6 @@ rs6000_ptrace_ldinfo (ptid_t ptid)
   return ldi;
 }
 
-/* Assuming ABFD refers to a core file, return the LdInfo data
-   stored in that core file.  Raises an error if the data could
-   not be read or extracted.
-
-   The returned value much be deallocated after use.  */
-
-static LdInfo *
-rs6000_core_ldinfo (bfd *abfd)
-{
-  struct bfd_section *ldinfo_sec;
-  int ldinfo_size;
-  gdb_byte *ldinfo_buf;
-  struct cleanup *cleanup;
-
-  ldinfo_sec = bfd_get_section_by_name (abfd, ".ldinfo");
-  if (ldinfo_sec == NULL)
-    error (_("cannot find .ldinfo section from core file: %s"),
-	   bfd_errmsg (bfd_get_error ()));
-  ldinfo_size = bfd_get_section_size (ldinfo_sec);
-
-  ldinfo_buf = xmalloc (ldinfo_size);
-  cleanup = make_cleanup (xfree, ldinfo_buf);
-
-  if (! bfd_get_section_contents (abfd, ldinfo_sec,
-				  ldinfo_buf, 0, ldinfo_size))
-    error (_("unable to read .ldinfo section from core file: %s"),
-	   bfd_errmsg (bfd_get_error ()));
-
-  discard_cleanups (cleanup);
-  return (LdInfo *) ldinfo_buf;
-}
-
-/* Append to OBJSTACK an XML string description of the shared library
-   corresponding to LDI, following the TARGET_OBJECT_LIBRARIES_AIX
-   format.  */
-
-static void
-rs6000_xfer_shared_library (LdInfo *ldi, struct obstack *obstack)
-{
-  const int arch64 = ARCH64 ();
-  const char *archive_name = LDI_FILENAME (ldi, arch64);
-  const char *member_name = archive_name + strlen (archive_name) + 1;
-  CORE_ADDR text_addr, data_addr;
-  ULONGEST text_size, data_size;
-  char *p;
-
-  if (arch64)
-    {
-      text_addr = ldi->l64.ldinfo_textorg;
-      text_size = ldi->l64.ldinfo_textsize;
-      data_addr = ldi->l64.ldinfo_dataorg;
-      data_size = ldi->l64.ldinfo_datasize;
-    }
-  else
-    {
-      /* The text and data addresses are defined as pointers.
-	 To avoid sign-extending their value in the assignments
-	 below, we cast their value to unsigned long first.  */
-      text_addr = (unsigned long) ldi->l32.ldinfo_textorg;
-      text_size = ldi->l32.ldinfo_textsize;
-      data_addr = (unsigned long) ldi->l32.ldinfo_dataorg;
-      data_size = ldi->l32.ldinfo_datasize;
-    }
-
-  obstack_grow_str (obstack, "<library name=\"");
-  p = xml_escape_text (archive_name);
-  obstack_grow_str (obstack, p);
-  xfree (p);
-  obstack_grow_str (obstack, "\"");
-
-  if (member_name[0] != '\0')
-    {
-      obstack_grow_str (obstack, " member=\"");
-      p = xml_escape_text (member_name);
-      obstack_grow_str (obstack, p);
-      xfree (p);
-      obstack_grow_str (obstack, "\"");
-    }
-
-  obstack_grow_str (obstack, " text_addr=\"");
-  obstack_grow_str (obstack, core_addr_to_string (text_addr));
-  obstack_grow_str (obstack, "\"");
-
-  obstack_grow_str (obstack, " text_size=\"");
-  obstack_grow_str (obstack, pulongest (text_size));
-  obstack_grow_str (obstack, "\"");
-
-  obstack_grow_str (obstack, " data_addr=\"");
-  obstack_grow_str (obstack, core_addr_to_string (data_addr));
-  obstack_grow_str (obstack, "\"");
-
-  obstack_grow_str (obstack, " data_size=\"");
-  obstack_grow_str (obstack, pulongest (data_size));
-  obstack_grow_str (obstack, "\"");
-
-  obstack_grow_str (obstack, "></library>");
-}
-
 /* Implement the to_xfer_partial target_ops method for
    TARGET_OBJECT_LIBRARIES_AIX objects.  */
 
@@ -819,62 +681,26 @@ rs6000_xfer_shared_libraries
    const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
    ULONGEST offset, LONGEST len)
 {
-  const int arch64 = ARCH64 ();
-  LdInfo *ldi_data;
-  LdInfo *ldi;
-  struct obstack obstack;
-  const char *buf;
-  LONGEST len_avail;
+  gdb_byte *ldi_buf;
+  ULONGEST result;
+  struct cleanup *cleanup;
+
+  /* This function assumes that it is being run with a live process.
+     Core files are handled via gdbarch.  */
+  gdb_assert (target_has_execution);
 
   if (writebuf)
     return -1;
 
-  /* Get the ldinfo raw data: If debugging a live process, we get it
-     using ptrace.  Otherwise, the info is stored in the .ldinfo
-     section of the core file.  */
-
-  if (target_has_execution)
-    ldi_data = rs6000_ptrace_ldinfo (inferior_ptid);
-  else
-    ldi_data = rs6000_core_ldinfo (core_bfd);
-
-  /* Convert the raw data into an XML representation.  */
-
-  obstack_init (&obstack);
-  obstack_grow_str (&obstack, "<library-list-aix version=\"1.0\">\n");
-
-  ldi = ldi_data;
-  while (1)
-    {
-      /* Close the fd.  We cannot use it, because we cannot assume
-	 that the user of this descriptor will be in the same
-	 process.  */
-      close (LDI_FD (ldi, arch64));
-
-      rs6000_xfer_shared_library (ldi, &obstack);
-
-      if (!LDI_NEXT (ldi, arch64))
-	break;
-      ldi = (LdInfo *) ((char *) ldi + LDI_NEXT (ldi, arch64));
-    }
-
-  xfree (ldi_data);
-
-  obstack_grow_str0 (&obstack, "</library-list-aix>\n");
-
-  buf = obstack_finish (&obstack);
-  len_avail = strlen (buf);
-  if (offset >= len_avail)
-    len= 0;
-  else
-    {
-      if (len > len_avail - offset)
-        len = len_avail - offset;
-      memcpy (readbuf, buf + offset, len);
-    }
+  ldi_buf = rs6000_ptrace_ldinfo (inferior_ptid);
+  gdb_assert (ldi_buf != NULL);
+  cleanup = make_cleanup (xfree, ldi_buf);
+  result = rs6000_aix_ld_info_to_xml (target_gdbarch (), ldi_buf,
+				      readbuf, offset, len, 1);
+  xfree (ldi_buf);
 
-  obstack_free (&obstack, NULL);
-  return len;
+  do_cleanups (cleanup);
+  return result;
 }
 
 void _initialize_rs6000_nat (void);
-- 
1.7.0.4


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