This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[4/8] Implement the ldopen() family of routines for cross collect2s


AIX collect2 currently relies on the ldopen()/ldclose() family of routines,
which are only available on AIX systems.  This patch tries to emulate the
routines for cross toolchains.

For the record, I did this work without referring to AIX header files,
and I have no access to the AIX code itself.  The file format definitions
were adapted from bfd code while everything else was written from scratch.
I used delimiters (usually frowned on, I know) to show which parts came
from bfd.

The main restrictions with this support are:

  (1) It requires mmap().

  (2) It only works for "big"-format archives.

It would be easy to add support for small archives, but I haven't had
chance to do that.  Small archives are of pretty niche importance
these days anyway.

collect2.c has one instance of a host-acting-as-target preprocessor check:

    #ifdef _AIX51

I replaced this with a new TARGET_AIX_VERSION macro.

Tested on powerpc-ibm-aix6.1 and x86_64-linux-gnu.  OK to install?

Richard


gcc/
	* Makefile.in (COLLECT2_OBJS): Add collect2-aix.o.
	(collect2.o): Depend on collect2-aix.h.
	(collect2-aix.o): New rule.
	* collect2-aix.h: New file.
	* collect2-aix.c: Likewise.
	* collect2.c: Include collect-aix.h.  Don't undefine OBJECT_FORMAT_COFF
	if CROSS_AIX_SUPPORT is defined.  Guard native includes with
	#ifndef CROSS_DIRECTORY_STRUCTURE.  Use TARGET_AIX_VERSION
	instead of _AIX51.
	* config/rs6000/aix43.h (TARGET_AIX_VERSION): Define.
	* config/rs6000/aix51.h (TARGET_AIX_VERSION): Likewise.
	* config/rs6000/aix52.h (TARGET_AIX_VERSION): Likewise.
	* config/rs6000/aix53.h (TARGET_AIX_VERSION): Likewise.
	* config/rs6000/aix61.h (TARGET_AIX_VERSION): Likewise.

Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	2009-06-02 13:06:03.000000000 +0100
+++ gcc/Makefile.in	2009-06-02 13:06:05.000000000 +0100
@@ -1897,7 +1897,7 @@ ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTE
 	$(EBITMAP_H) $(RTL_H) $(FLAGS_H) $(OBSTACK_H)
 sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
 
-COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
+COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o intl.o version.o
 COLLECT2_LIBS = @COLLECT2_LIBS@
 collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
 # Don't try modifying collect2 (aka ld) in place--it might be linking this.
@@ -1906,10 +1906,13 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LI
 	mv -f T$@ $@
 
 collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h \
-	$(OBSTACK_H) $(DEMANGLE_H) collect2.h version.h
+	$(OBSTACK_H) $(DEMANGLE_H) collect2.h collect2-aix.h version.h
 	$(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS)  \
 	-DTARGET_MACHINE=\"$(target_noncanonical)\" \
-	-c $(srcdir)/collect2.c $(OUTPUT_OPTION)
+	-c $(srcdir)/collect2.c $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
+
+collect2-aix.o : collect2-aix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+    collect2-aix.h
 
 tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(OBSTACK_H) collect2.h intl.h
Index: gcc/collect2-aix.h
===================================================================
--- /dev/null	2009-05-22 08:46:47.449511000 +0100
+++ gcc/collect2-aix.h	2009-06-02 13:06:05.000000000 +0100
@@ -0,0 +1,301 @@
+/* AIX cross support for collect2.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* collect2-aix.c requires mmap support.  It should otherwise be
+   fairly portable.  */
+#if defined(CROSS_DIRECTORY_STRUCTURE) \
+    && defined(TARGET_AIX_VERSION) \
+    && HAVE_MMAP
+
+#define CROSS_AIX_SUPPORT 1
+
+/* -------------------------------------------------------------------------
+   Definitions adapted from bfd.  (Fairly heavily adapted in some cases.)
+   ------------------------------------------------------------------------- */
+
+/* Compatiblity types for bfd.  */
+typedef unsigned HOST_WIDE_INT bfd_vma;
+
+/* The size of an archive's fl_magic field.  */
+#define FL_MAGIC_SIZE 8
+
+/* The expected contents of fl_magic for big archives.  */
+#define FL_MAGIC_BIG_AR "<bigaf>\012"
+
+/* The size of each offset string in the header of a big archive.  */
+#define AR_BIG_OFFSET_SIZE 20
+
+/* The format of the file header in a "big" XCOFF archive.  */
+struct external_big_ar_filehdr
+{
+  /* Magic string.  */
+  char fl_magic[FL_MAGIC_SIZE];
+
+  /* Offset of the member table (decimal ASCII string).  */
+  char fl_memoff[AR_BIG_OFFSET_SIZE];
+
+  /* Offset of the global symbol table for 32-bit objects (decimal ASCII
+     string).  */
+  char fl_symoff[AR_BIG_OFFSET_SIZE];
+
+  /* Offset of the global symbol table for 64-bit objects (decimal ASCII
+     string).  */
+  char fl_symoff64[AR_BIG_OFFSET_SIZE];
+
+  /* Offset of the first member in the archive (decimal ASCII string).  */
+  char fl_firstmemoff[AR_BIG_OFFSET_SIZE];
+
+  /* Offset of the last member in the archive (decimal ASCII string).  */
+  char fl_lastmemoff[AR_BIG_OFFSET_SIZE];
+
+  /* Offset of the first member on the free list (decimal ASCII
+     string).  */
+  char fl_freeoff[AR_BIG_OFFSET_SIZE];
+};
+
+/* Each archive name is followed by this many bytes of magic string.  */
+#define SXCOFFARFMAG 2
+
+/* The format of a member header in a "big" XCOFF archive.  */
+struct external_big_ar_member
+{
+  /* File size not including the header (decimal ASCII string).  */
+  char ar_size[AR_BIG_OFFSET_SIZE];
+
+  /* File offset of next archive member (decimal ASCII string).  */
+  char ar_nextoff[AR_BIG_OFFSET_SIZE];
+
+  /* File offset of previous archive member (decimal ASCII string).  */
+  char ar_prevoff[AR_BIG_OFFSET_SIZE];
+
+  /* File mtime (decimal ASCII string).  */
+  char ar_date[12];
+
+  /* File UID (decimal ASCII string).  */
+  char ar_uid[12];
+
+  /* File GID (decimal ASCII string).  */
+  char ar_gid[12];
+
+  /* File mode (octal ASCII string).  */
+  char ar_mode[12];
+
+  /* Length of file name (decimal ASCII string).  */
+  char ar_namlen[4];
+
+  /* This structure is followed by the file name.  The length of the
+     name is given in the namlen field.  If the length of the name is
+     odd, the name is followed by a null byte.  The name and optional
+     null byte are followed by XCOFFARFMAG, which is not included in
+     namlen.  The contents of the archive member follow; the number of
+     bytes is given in the size field.  */
+};
+
+/* The known values of f_magic in an XCOFF file header.  */
+#define U802WRMAGIC 0730	/* Writeable text segments.  */
+#define U802ROMAGIC 0735	/* Readonly sharable text segments.  */
+#define U802TOCMAGIC 0737	/* Readonly text segments and TOC.  */
+#define U803XTOCMAGIC 0757	/* Aix 4.3 64-bit XCOFF.  */
+#define U64_TOCMAGIC 0767	/* AIX 5+ 64-bit XCOFF.  */
+
+/* The number of bytes in an XCOFF file's f_magic field.  */
+#define F_MAGIC_SIZE 2
+
+/* The format of a 32-bit XCOFF file header.  */
+struct external_filehdr_32
+{
+  /* The magic number.  */
+  char f_magic[F_MAGIC_SIZE];
+
+  /* The number of sections.  */
+  char f_nscns[2];
+
+  /* Time & date stamp.  */
+  char f_timdat[4];
+
+  /* The offset of the symbol table from the start of the file.  */
+  char f_symptr[4];
+
+  /* The number of entries in the symbol table.  */
+  char f_nsyms[4];
+
+  /* The size of the auxillary header.  */
+  char f_opthdr[2];
+
+  /* Flags.  */
+  char f_flags[2];
+};
+
+/* The format of a 64-bit XCOFF file header.  */
+struct external_filehdr_64
+{
+  /* The magic number.  */
+  char f_magic[F_MAGIC_SIZE];
+
+  /* The number of sections.  */
+  char f_nscns[2];
+
+  /* Time & date stamp.  */
+  char f_timdat[4];
+
+  /* The offset of the symbol table from the start of the file.  */
+  char f_symptr[8];
+
+  /* The size of the auxillary header.  */
+  char f_opthdr[2];
+
+  /* Flags.  */
+  char f_flags[2];
+
+  /* The number of entries in the symbol table.  */
+  char f_nsyms[4];
+};
+
+/* An internal representation of the XCOFF file header.  */
+struct internal_filehdr
+{
+  unsigned short f_magic;
+  unsigned short f_nscns;
+  long f_timdat;
+  bfd_vma f_symptr;
+  long f_nsyms;
+  unsigned short f_opthdr;
+  unsigned short f_flags;
+};
+
+/* Symbol classes have their names in the debug section if this flag
+   is set.  */
+#define DBXMASK 0x80
+
+/* The format of an XCOFF symbol-table entry.  */
+struct external_syment
+{
+  union {
+    struct {
+      union {
+	/* The name of the symbol.  There is an implicit null character
+	   after the end of the array.  */
+	char n_name[8];
+	struct {
+	  /* If n_zeroes is zero, n_offset is the offset the name from
+	     the start of the string table.  */
+	  char n_zeroes[4];
+	  char n_offset[4];
+	} u;
+      } u;
+
+      /* The symbol's value.  */
+      char n_value[4];
+    } xcoff32;
+    struct {
+      /* The symbol's value.  */
+      char n_value[8];
+
+      /* The offset of the symbol from the start of the string table.  */
+      char n_offset[4];
+    } xcoff64;
+  } u;
+
+  /* The number of the section to which this symbol belongs.  */
+  char n_scnum[2];
+
+  /* The type of symbol.  (It can be interpreted as an n_lang
+     and an n_cpu byte, but we don't care about that here.)  */
+  char n_type[2];
+
+  /* The class of symbol (a C_* value).  */
+  char n_sclass[1];
+
+  /* The number of auxillary symbols attached to this entry.  */
+  char n_numaux[1];
+};
+
+/* Definitions required by collect2.  */
+#define C_EXT 2
+
+#define F_SHROBJ 0x2000
+
+#define N_UNDEF ((short) 0)
+#define N_TMASK 060
+#define N_BTSHFT 4
+
+#define DT_NON 0
+#define DT_FCN 2
+
+/* -------------------------------------------------------------------------
+   Local code.
+   ------------------------------------------------------------------------- */
+
+/* An internal representation of an XCOFF symbol-table entry,
+   which is associated with the API-defined SYMENT type.  */
+struct internal_syment
+{
+  char n_name[9];
+  unsigned int n_zeroes;
+  bfd_vma n_offset;
+  bfd_vma n_value;
+  short n_scnum;
+  unsigned short n_flags;
+  unsigned short n_type;
+  unsigned char n_sclass;
+  unsigned char n_numaux;
+};
+typedef struct internal_syment SYMENT;
+
+/* The internal representation of the API-defined LDFILE type.  */
+struct internal_ldfile
+{
+  /* The file handle for the associated file, or -1 if it hasn't been
+     opened yet.  */
+  int fd;
+
+  /* The start of the current XCOFF object, if one has been mapped
+     into memory.  Null otherwise.  */
+  char *object;
+
+  /* The offset of OBJECT from the start of the containing page.  */
+  size_t page_offset;
+
+  /* The size of the file pointed to by OBJECT.  Valid iff OFFSET
+     is nonnull.  */
+  size_t object_size;
+
+  /* The offset of the next member in an archive after OBJECT,
+     or -1 if this isn't an archive.  Valid iff OFFSET is nonnull.  */
+  off_t next_member;
+
+  /* The parsed version of the XCOFF file header.  */
+  struct internal_filehdr filehdr;
+};
+typedef struct internal_ldfile LDFILE;
+
+/* The API allows the file header to be directly accessed via this macro.  */
+#define HEADER(FILE) ((FILE)->filehdr)
+
+/* API-defined return codes.  SUCCESS must be > 0 and FAILURE must be <= 0.  */
+#define SUCCESS 1
+#define FAILURE 0
+
+/* API-defined functions.  */
+extern LDFILE *ldopen (char *, LDFILE *);
+extern char *ldgetname (LDFILE *, SYMENT *);
+extern int ldtbread (LDFILE *, long, SYMENT *);
+extern int ldclose (LDFILE *);
+
+#endif
Index: gcc/collect2-aix.c
===================================================================
--- /dev/null	2009-05-22 08:46:47.449511000 +0100
+++ gcc/collect2-aix.c	2009-06-02 13:06:05.000000000 +0100
@@ -0,0 +1,371 @@
+/* AIX cross support for collect2.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "collect2-aix.h"
+
+#ifdef CROSS_AIX_SUPPORT
+
+#include <sys/mman.h>
+
+/* Read SIZE bytes starting at DATA as a big-endian value.  */
+
+static inline bfd_vma
+read_value (char *data, unsigned int size)
+{
+  bfd_vma value;
+  unsigned int i;
+
+  value = 0;
+  for (i = 0; i < size; i++)
+    {
+      value <<= 8;
+      value += (unsigned char) data[i];
+    }
+  return value;
+}
+
+/* FIELD is a char array.  Read the contents as a big-endian integer.  */
+#define READ_FIELD(FIELD) \
+  read_value (FIELD, sizeof (FIELD))
+
+/* OBJECT is a char pointer to an in-file object of type struct TYPE.
+   Return the address of field FIELD.  */
+#define OBJECT_FIELD(OBJECT, TYPE, FIELD) \
+  (OBJECT) + offsetof (struct TYPE, FIELD)
+
+/* Return the size of FIELD, which is a field of struct TYPE.  */
+#define FIELD_SIZE(TYPE, FIELD) \
+  sizeof (((struct TYPE *) (0))->FIELD)
+
+/* OBJECT is a char pointer to an in-file object of type struct TYPE.
+   Read the value of field FIELD as a big-endian integer.  */
+#define READ_OBJECT(OBJECT, TYPE, FIELD) \
+  read_value (OBJECT_FIELD (OBJECT, TYPE, FIELD), FIELD_SIZE (TYPE, FIELD))
+
+/* Copy FIELD from an external structure of type TYPE at address FROM
+   to an internal structure pointed to by TO.  */
+#define COPY_FIELD(TO, FROM, TYPE, FIELD) \
+  ((TO)->FIELD = READ_OBJECT (FROM, TYPE, FIELD))
+
+/* Return true if STRING is less than SIZE bytes long.  EXTRA_TERMINATOR
+   is another character (besides '\0') that acts as a terminator,
+   or '\0' if none.  */
+
+static bool
+string_within_bounds_p (const char *string, size_t size, char extra_terminator)
+{
+  const char *p;
+
+  for (p = string; p < string + size; p++)
+    if (*p == '\0' || *p == extra_terminator)
+      return true;
+  return false;
+}
+
+/* STRING is a pointer to a char array.  Try to read its value as an
+   ASCII-encoded integer.  On success, return true and store the result
+   in TARGET.  */
+#define PARSE_INTEGER(TARGET, STRING) \
+  (string_within_bounds_p (&(STRING)[0], sizeof (STRING), ' ') \
+   && ((TARGET) = strtoul (STRING, NULL, 0), true))
+
+/* Check that LDFILE's current object has SIZE bytes starting at OFFSET.  */
+
+static inline bool
+within_object_p (LDFILE *ldfile, size_t offset, size_t size)
+{
+  return offset <= ldfile->object_size && offset + size <= ldfile->object_size;
+}
+
+/* Try to read the file header for an XCOFF object at OFFSET bytes into
+   LDFILE.  The object is expected to be OBJECT_SIZE bytes in size.
+   If the object is a member of an archive, NEXT_MEMBER is the offset
+   of the next member, otherwise it is -1.
+
+   Return true on success, recording the object information in LDFILE.  */
+
+static bool
+read_xcoff_object (LDFILE *ldfile, size_t offset, size_t object_size,
+		   off_t next_member)
+{
+  struct internal_filehdr *internal;
+  char *external;
+  void *map;
+  size_t page_size;
+
+  /* First try to map the file into memory.  */
+  page_size = getpagesize ();
+  ldfile->page_offset = offset & (page_size - 1);
+  map = mmap (NULL, object_size + ldfile->page_offset, PROT_READ,
+              MAP_SHARED, ldfile->fd, offset - ldfile->page_offset);
+  if (map == MAP_FAILED)
+    return false;
+
+  /* Record the success.  */
+  ldfile->object = (char *) map + ldfile->page_offset;
+  ldfile->object_size = object_size;
+  ldfile->next_member = next_member;
+
+  /* Read the magic value to determine the type of file.  */
+  if (!within_object_p (ldfile, 0, F_MAGIC_SIZE))
+    return false;
+
+  internal = &ldfile->filehdr;
+  external = ldfile->object;
+  internal->f_magic = read_value (external, F_MAGIC_SIZE);
+  if (internal->f_magic == U802TOCMAGIC)
+    {
+      if (!within_object_p (ldfile, 0, sizeof (struct external_filehdr_32)))
+	return false;
+
+      COPY_FIELD (internal, external, external_filehdr_32, f_nscns);
+      COPY_FIELD (internal, external, external_filehdr_32, f_timdat);
+      COPY_FIELD (internal, external, external_filehdr_32, f_symptr);
+      COPY_FIELD (internal, external, external_filehdr_32, f_nsyms);
+      COPY_FIELD (internal, external, external_filehdr_32, f_opthdr);
+      COPY_FIELD (internal, external, external_filehdr_32, f_flags);
+      return true;
+    }
+  else if (internal->f_magic == U803XTOCMAGIC
+	   || internal->f_magic == U64_TOCMAGIC)
+    {
+      if (!within_object_p (ldfile, 0, sizeof (struct external_filehdr_64)))
+	return false;
+
+      COPY_FIELD (internal, external, external_filehdr_64, f_nscns);
+      COPY_FIELD (internal, external, external_filehdr_64, f_timdat);
+      COPY_FIELD (internal, external, external_filehdr_64, f_symptr);
+      COPY_FIELD (internal, external, external_filehdr_64, f_nsyms);
+      COPY_FIELD (internal, external, external_filehdr_64, f_opthdr);
+      COPY_FIELD (internal, external, external_filehdr_64, f_flags);
+      return true;
+    }
+  return false;
+}
+
+/* Try to read an archive member at OFFSET bytes into LDFILE.
+   Return true on success, recording the member and object
+   information in LDFILE.  */
+
+static bool
+read_archive_member (LDFILE *ldfile, size_t offset)
+{
+  struct external_big_ar_member member;
+  size_t namlen;
+  size_t size;
+  off_t next_member;
+
+  if (lseek (ldfile->fd, offset, SEEK_SET) >= 0
+      && read (ldfile->fd, &member, sizeof (member)) == sizeof (member)
+      && PARSE_INTEGER (namlen, member.ar_namlen)
+      /* Stop once we reach the member table entry, which has a name
+	 of length 0.  */
+      && namlen > 0
+      && PARSE_INTEGER (size, member.ar_size)
+      && PARSE_INTEGER (next_member, member.ar_nextoff))
+    {
+      /* The archive is followed by an even-padded name, then by
+	 a magic string of length SXCOFFARFMAG.  The object itself
+	 starts after that. */
+      offset += sizeof (member) + namlen + SXCOFFARFMAG;
+      offset += offset & 1;
+      return read_xcoff_object (ldfile, offset, size, next_member);
+    }
+  return false;
+}
+
+/* Try to treat LDFILE as a non-empty big archive.  Return true
+   on success, storing the member and object information for
+   the first member in LDFILE.  */
+
+static bool
+read_big_archive (LDFILE *ldfile)
+{
+  struct external_big_ar_filehdr filehdr;
+  size_t offset;
+
+  return (lseek (ldfile->fd, 0L, SEEK_SET) == 0
+	  && read (ldfile->fd, &filehdr, sizeof (filehdr)) == sizeof (filehdr)
+	  && memcmp (filehdr.fl_magic, FL_MAGIC_BIG_AR, FL_MAGIC_SIZE) == 0
+	  && PARSE_INTEGER (offset, filehdr.fl_firstmemoff)
+	  && read_archive_member (ldfile, offset));
+}
+
+/* LDFILE is a zero-initialized structure.  Try to open FILENAME,
+   returning true on success.  */
+
+static bool
+open_file (LDFILE *ldfile, const char *filename)
+{
+  struct stat st;
+
+  ldfile->fd = open (filename, O_RDONLY);
+  if (ldfile->fd < 0)
+    return false;
+
+  if (read_big_archive (ldfile))
+    return true;
+
+  if (fstat (ldfile->fd, &st) < 0)
+    return false;
+
+  return read_xcoff_object (ldfile, 0, st.st_size, -1);
+}
+
+/* Release the memory associated with the current object, if one has
+   been mapped.  */
+
+static void
+free_object (LDFILE *ldfile)
+{
+  if (ldfile->object)
+    munmap (ldfile->object - ldfile->page_offset,
+	    ldfile->object_size + ldfile->page_offset);
+}
+
+/* Free LDFILE and all resources associated with it.  */
+
+static void
+free_ldfile (LDFILE *ldfile)
+{
+  if (ldfile->fd >= 0)
+    close (ldfile->fd);
+  XDELETE (ldfile);
+}
+
+/* Implement the API-defined ldopen function.  */
+
+LDFILE *
+ldopen (char *filename, LDFILE *ldfile)
+{
+  if (ldfile == NULL)
+    {
+      ldfile = XCNEW (LDFILE);
+      if (!open_file (ldfile, filename))
+	{
+	  free_object (ldfile);
+	  free_ldfile (ldfile);
+	  return NULL;
+	}
+    }
+  return ldfile;
+}
+
+/* Implement the API-defined ldtbread function.  */
+
+int
+ldtbread (LDFILE *ldfile, long index, SYMENT *internal)
+{
+  size_t offset, name_length;
+  char *external;
+
+  /* Make sure that the symbol index is valid.  */
+  if (index < 0 || index >= HEADER (ldfile).f_nsyms)
+    return FAILURE;
+
+  /* Work out the offset of the symbol table entry.  */
+  offset = HEADER (ldfile).f_symptr + index * sizeof (struct external_syment);
+  if (!within_object_p (ldfile, offset, sizeof (struct external_syment)))
+    return FAILURE;
+
+  /* Read all the fields.  The format differs between 32-bit and
+     64-bit files.  */
+  external = ldfile->object + offset;
+  if (HEADER (ldfile).f_magic == U802TOCMAGIC)
+    {
+      /* Copy the n_zeroes/n_offset interpretation.  */
+      internal->n_zeroes = READ_OBJECT (external, external_syment,
+					u.xcoff32.u.u.n_zeroes);
+      internal->n_offset = READ_OBJECT (external, external_syment,
+					u.xcoff32.u.u.n_offset);
+
+      /* Copy the n_name interpretation.  The internal version has room
+	 for a null terminator.  */
+      name_length = FIELD_SIZE (external_syment, u.xcoff32.u.n_name);
+      memcpy (internal->n_name,
+	      external + offsetof (struct external_syment, u.xcoff32.u.n_name),
+	      name_length);
+      internal->n_name[name_length] = 0;
+
+      internal->n_value = READ_OBJECT (external, external_syment,
+				       u.xcoff32.n_value);
+    }
+  else
+    {
+      internal->n_zeroes = 0;
+      internal->n_offset = READ_OBJECT (external, external_syment,
+					u.xcoff64.n_offset);
+      internal->n_value = READ_OBJECT (external, external_syment,
+				       u.xcoff64.n_value);
+    }
+  COPY_FIELD (internal, external, external_syment, n_scnum);
+  COPY_FIELD (internal, external, external_syment, n_type);
+  COPY_FIELD (internal, external, external_syment, n_sclass);
+  COPY_FIELD (internal, external, external_syment, n_numaux);
+  return SUCCESS;
+}
+
+/* Implement the API-defined ldgetname function.  */
+
+char *
+ldgetname (LDFILE *ldfile, SYMENT *symbol)
+{
+  char *name;
+  size_t offset;
+
+  /* If the zeroes field is nonzero, the name is in the symbol table
+     entry itself.  */
+  if (symbol->n_zeroes != 0)
+    return symbol->n_name;
+
+  /* Otherwise, the symbol table entry contains an offset into the
+     string table, which starts after the end of the symbol table.  */
+  offset = (HEADER (ldfile).f_symptr
+	    + HEADER (ldfile).f_nsyms * sizeof (struct external_syment)
+	    + symbol->n_offset);
+  if (offset >= ldfile->object_size)
+    return NULL;
+
+  /* Make sure that the name is entirely contained within the object.  */
+  name = ldfile->object + offset;
+  if (!string_within_bounds_p (name, ldfile->object_size - offset, '\0'))
+    return NULL;
+
+  return name;
+}
+
+/* Implement the API-defined ldclose function.  */
+
+int
+ldclose (LDFILE *ldfile)
+{
+  free_object (ldfile);
+  if (ldfile->next_member >= 0
+      && read_archive_member (ldfile, ldfile->next_member))
+    return FAILURE;
+
+  free_ldfile (ldfile);
+  return SUCCESS;
+}
+
+#endif
Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c	2009-06-02 13:06:04.000000000 +0100
+++ gcc/collect2.c	2009-06-02 13:06:05.000000000 +0100
@@ -42,6 +42,7 @@ #define LIBRARY_PATH_ENV "LIBRARY_PATH"
 #define COLLECT
 
 #include "collect2.h"
+#include "collect2-aix.h"
 #include "demangle.h"
 #include "obstack.h"
 #include "intl.h"
@@ -54,7 +55,9 @@ #define COLLECT
    cross-versions are in the proper directories.  */
 
 #ifdef CROSS_DIRECTORY_STRUCTURE
+#ifndef CROSS_AIX_SUPPORT
 #undef OBJECT_FORMAT_COFF
+#endif
 #undef MD_EXEC_PREFIX
 #undef REAL_LD_FILE_NAME
 #undef REAL_NM_FILE_NAME
@@ -72,6 +75,7 @@ #define OBJECT_FORMAT_NONE
 
 #ifdef OBJECT_FORMAT_COFF
 
+#ifndef CROSS_DIRECTORY_STRUCTURE
 #include <a.out.h>
 #include <ar.h>
 
@@ -86,6 +90,7 @@ #define OBJECT_FORMAT_NONE
 #endif
 
 #include <ldfcn.h>
+#endif
 
 /* Some systems have an ISCOFF macro, but others do not.  In some cases
    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
@@ -2404,7 +2409,7 @@ scan_libraries (const char *prog_name)
 #   define GCC_SYMZERO(X)	0
 
 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
-#ifdef _AIX51
+#if TARGET_AIX_VERSION >= 51
 #   define GCC_CHECK_HDR(X) \
      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
       || (HEADER (X).f_magic == 0767 && aix64_flag))
Index: gcc/config/rs6000/aix43.h
===================================================================
--- gcc/config/rs6000/aix43.h	2009-06-02 13:06:03.000000000 +0100
+++ gcc/config/rs6000/aix43.h	2009-06-02 13:06:05.000000000 +0100
@@ -187,3 +187,5 @@ #define TARGET_DEFERRED_OUTPUT_DEFS(DECL
 
 /* This target uses the aix64.opt file.  */
 #define TARGET_USES_AIX64_OPT 1
+
+#define TARGET_AIX_VERSION 43
Index: gcc/config/rs6000/aix51.h
===================================================================
--- gcc/config/rs6000/aix51.h	2009-06-02 13:06:03.000000000 +0100
+++ gcc/config/rs6000/aix51.h	2009-06-02 13:06:05.000000000 +0100
@@ -191,3 +191,5 @@ #define TARGET_USES_AIX64_OPT 1
    but does not have crtbegin/end.  */
 
 #define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 51
Index: gcc/config/rs6000/aix52.h
===================================================================
--- gcc/config/rs6000/aix52.h	2009-06-02 13:06:03.000000000 +0100
+++ gcc/config/rs6000/aix52.h	2009-06-02 13:06:05.000000000 +0100
@@ -201,3 +201,5 @@ #define TARGET_USES_AIX64_OPT 1
    but does not have crtbegin/end.  */
 
 #define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 52
Index: gcc/config/rs6000/aix53.h
===================================================================
--- gcc/config/rs6000/aix53.h	2009-06-02 13:06:03.000000000 +0100
+++ gcc/config/rs6000/aix53.h	2009-06-02 13:06:05.000000000 +0100
@@ -197,3 +197,5 @@ #define TARGET_USES_AIX64_OPT 1
    but does not have crtbegin/end.  */
 
 #define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 53
Index: gcc/config/rs6000/aix61.h
===================================================================
--- gcc/config/rs6000/aix61.h	2009-06-02 13:06:03.000000000 +0100
+++ gcc/config/rs6000/aix61.h	2009-06-02 13:06:05.000000000 +0100
@@ -202,3 +202,5 @@ #define TARGET_USE_JCR_SECTION 0
 /* Default to 128 bit long double.  */
 
 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
+
+#define TARGET_AIX_VERSION 61


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