+2013-05-15 Joel Brobecker <brobecker@adacore.com>
+
+ * 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.
+
2013-05-15 Markus Metzger <markus.t.metzger@intel.com>
* record.c (record_goto_cmdlist): New.
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 \
}
/* 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)
{
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;
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 */
/* 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 */
fprintf_unfiltered (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));
gdbarch->core_xfer_shared_libraries = core_xfer_shared_libraries;
}
+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)
{
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);
# 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
#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
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)
{
/* 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;
--- /dev/null
+/* 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 */
#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"
#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
# 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
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)
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. */
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);