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]

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


Hello,

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 results in the following warning:

    (gdb) core core
    warning: unable to relocate main executable (failed to read TARGET_OBJECT_LIBRARIES_AIX)
    warning: while parsing aix library list: no element found
    Core was generated by `crash'.
    [...]

This patch fixes the problem by extending corelow's core_xfer_partial
into handling the TARGET_OBJECT_LIBRARIES_AIX object. This requires
that we go through the gdbarch vector rather than just purely the
target_ops. This means that I needed the code decoding the loader
info to be in the aix-tdep module, which also forces me to extract
the data from that loader info by hand. We're lucky, the information
appears to be stable across platforms.

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.

Tested on ppc-aix 5.3 and 7.1.

Comments? If at all possible, I'd like to commit relatively quickly,
since this is a regression...

Thanks,
-- 
Joel

---
 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..450abae 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
+{
+  int 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_signed_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.6.5.rc2


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