From dfb636dcd052f5f68ba6abf5b9041c3c63562438 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 2 Jun 2009 19:06:56 +0000 Subject: [PATCH] Makefile.in (COLLECT2_OBJS): Add collect2-aix.o. 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 collect2-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. From-SVN: r148096 --- gcc/ChangeLog | 17 ++ gcc/Makefile.in | 9 +- gcc/collect2-aix.c | 371 ++++++++++++++++++++++++++++++++++++++ gcc/collect2-aix.h | 301 +++++++++++++++++++++++++++++++ gcc/collect2.c | 7 +- gcc/config/rs6000/aix43.h | 2 + gcc/config/rs6000/aix51.h | 2 + gcc/config/rs6000/aix52.h | 2 + gcc/config/rs6000/aix53.h | 2 + gcc/config/rs6000/aix61.h | 2 + 10 files changed, 711 insertions(+), 4 deletions(-) create mode 100644 gcc/collect2-aix.c create mode 100644 gcc/collect2-aix.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d56760b6d8c..06f8e77d3f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2009-06-02 Richard Sandiford + + * 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 collect2-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. + 2009-06-02 Richard Sandiford * collect2.c (ignore_library): Avoid premature post-increment diff --git a/gcc/Makefile.in b/gcc/Makefile.in index e76e256c78d..381c189960c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1897,7 +1897,7 @@ ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(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) $(LIBDEPS) 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 diff --git a/gcc/collect2-aix.c b/gcc/collect2-aix.c new file mode 100644 index 00000000000..7d25e7e6b89 --- /dev/null +++ b/gcc/collect2-aix.c @@ -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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "collect2-aix.h" + +#ifdef CROSS_AIX_SUPPORT + +#include + +/* 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 diff --git a/gcc/collect2-aix.h b/gcc/collect2-aix.h new file mode 100644 index 00000000000..1ab313d0f34 --- /dev/null +++ b/gcc/collect2-aix.h @@ -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 +. */ + +/* 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 "\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 diff --git a/gcc/collect2.c b/gcc/collect2.c index a500147e563..660664dd29a 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #define COLLECT #include "collect2.h" +#include "collect2-aix.h" #include "demangle.h" #include "obstack.h" #include "intl.h" @@ -54,7 +55,9 @@ along with GCC; see the file COPYING3. If not see 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 @@ along with GCC; see the file COPYING3. If not see #ifdef OBJECT_FORMAT_COFF +#ifndef CROSS_DIRECTORY_STRUCTURE #include #include @@ -86,6 +90,7 @@ along with GCC; see the file COPYING3. If not see #endif #include +#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 @@ -2409,7 +2414,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)) diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h index 4b769ca8d87..bbe23373060 100644 --- a/gcc/config/rs6000/aix43.h +++ b/gcc/config/rs6000/aix43.h @@ -187,3 +187,5 @@ do { \ /* This target uses the aix64.opt file. */ #define TARGET_USES_AIX64_OPT 1 + +#define TARGET_AIX_VERSION 43 diff --git a/gcc/config/rs6000/aix51.h b/gcc/config/rs6000/aix51.h index 7bac90a3f00..32bdbb41f28 100644 --- a/gcc/config/rs6000/aix51.h +++ b/gcc/config/rs6000/aix51.h @@ -191,3 +191,5 @@ do { \ but does not have crtbegin/end. */ #define TARGET_USE_JCR_SECTION 0 + +#define TARGET_AIX_VERSION 51 diff --git a/gcc/config/rs6000/aix52.h b/gcc/config/rs6000/aix52.h index e1fcfa9516b..8d6c2411621 100644 --- a/gcc/config/rs6000/aix52.h +++ b/gcc/config/rs6000/aix52.h @@ -201,3 +201,5 @@ extern long long int atoll(const char *); but does not have crtbegin/end. */ #define TARGET_USE_JCR_SECTION 0 + +#define TARGET_AIX_VERSION 52 diff --git a/gcc/config/rs6000/aix53.h b/gcc/config/rs6000/aix53.h index e941fa48277..6172e76aad2 100644 --- a/gcc/config/rs6000/aix53.h +++ b/gcc/config/rs6000/aix53.h @@ -197,3 +197,5 @@ extern long long int atoll(const char *); but does not have crtbegin/end. */ #define TARGET_USE_JCR_SECTION 0 + +#define TARGET_AIX_VERSION 53 diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h index f3f31ac6e14..c0899d8c513 100644 --- a/gcc/config/rs6000/aix61.h +++ b/gcc/config/rs6000/aix61.h @@ -202,3 +202,5 @@ extern long long int atoll(const char *); /* Default to 128 bit long double. */ #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 + +#define TARGET_AIX_VERSION 61