+ gdb_assert (bfd_get_flavour (abfd) == bfd_target_xcoff_flavour);
+
+ /* The only noticeable difference between Lynx178 XCOFF files and
+ AIX XCOFF files comes from the fact that there are no shared
+ libraries on Lynx178. On AIX, we are betting that an executable
+ linked with no shared library will never exist. */
+ if (xcoff_get_n_import_files (abfd) <= 0)
+ return GDB_OSABI_UNKNOWN;
+
+ 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)
+{
+ obstack_grow_str (obstack, "<library name=\"");
+ std::string p = xml_escape_text (ldi->filename);
+ obstack_grow_str (obstack, p.c_str ());
+ obstack_grow_str (obstack, "\"");