/* BFD back-end for IBM RS/6000 "XCOFF" files.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
FIXME: Can someone provide a transliteration of this name into ASCII?
Using the following chars caused a compiler warning on HIUX (so I replaced
them with octal escapes), and isn't useful without an understanding of what
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
-#include "obstack.h"
#include "coff/internal.h"
#include "coff/rs6000.h"
#include "libcoff.h"
+/* The main body of code is in coffcode.h. */
+
+static boolean xcoff_mkobject PARAMS ((bfd *));
+static boolean xcoff_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean xcoff_is_local_label_name PARAMS ((bfd *, const char *));
+static void xcoff_rtype2howto
+ PARAMS ((arelent *, struct internal_reloc *));
+static reloc_howto_type *xcoff_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
static boolean xcoff_slurp_armap PARAMS ((bfd *));
static const bfd_target *xcoff_archive_p PARAMS ((bfd *));
static PTR xcoff_read_ar_hdr PARAMS ((bfd *));
static boolean xcoff_write_armap
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
static boolean xcoff_write_archive_contents PARAMS ((bfd *));
+static int _bfd_xcoff_sizeof_headers PARAMS ((bfd *, boolean));
+\f
+/* We use our own tdata type. Its first field is the COFF tdata type,
+ so the COFF routines are compatible. */
-/* The main body of code is in coffcode.h. */
+static boolean
+xcoff_mkobject (abfd)
+ bfd *abfd;
+{
+ coff_data_type *coff;
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+ abfd->tdata.xcoff_obj_data =
+ ((struct xcoff_tdata *)
+ bfd_zalloc (abfd, sizeof (struct xcoff_tdata)));
+ if (abfd->tdata.xcoff_obj_data == NULL)
+ return false;
+ coff = coff_data (abfd);
+ coff->symbols = (coff_symbol_type *) NULL;
+ coff->conversion_table = (unsigned int *) NULL;
+ coff->raw_syments = (struct coff_ptr_struct *) NULL;
+ coff->relocbase = 0;
+
+ xcoff_data (abfd)->modtype = ('1' << 8) | 'L';
+
+ /* We set cputype to -1 to indicate that it has not been
+ initialized. */
+ xcoff_data (abfd)->cputype = -1;
+
+ xcoff_data (abfd)->csects = NULL;
+ xcoff_data (abfd)->debug_indices = NULL;
+
+ return true;
+}
+
+/* Copy XCOFF data from one BFD to another. */
+
+static boolean
+xcoff_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ struct xcoff_tdata *ix, *ox;
+ asection *sec;
+
+ if (ibfd->xvec != obfd->xvec)
+ return true;
+ ix = xcoff_data (ibfd);
+ ox = xcoff_data (obfd);
+ ox->full_aouthdr = ix->full_aouthdr;
+ ox->toc = ix->toc;
+ if (ix->sntoc == 0)
+ ox->sntoc = 0;
+ else
+ {
+ sec = coff_section_from_bfd_index (ibfd, ix->sntoc);
+ if (sec == NULL)
+ ox->sntoc = 0;
+ else
+ ox->sntoc = sec->output_section->target_index;
+ }
+ if (ix->snentry == 0)
+ ox->snentry = 0;
+ else
+ {
+ sec = coff_section_from_bfd_index (ibfd, ix->snentry);
+ if (sec == NULL)
+ ox->snentry = 0;
+ else
+ ox->snentry = sec->output_section->target_index;
+ }
+ ox->text_align_power = ix->text_align_power;
+ ox->data_align_power = ix->data_align_power;
+ ox->modtype = ix->modtype;
+ ox->cputype = ix->cputype;
+ ox->maxdata = ix->maxdata;
+ ox->maxstack = ix->maxstack;
+ return true;
+}
+
+/* I don't think XCOFF really has a notion of local labels based on
+ name. This will mean that ld -X doesn't actually strip anything.
+ The AIX native linker does not have a -X option, and it ignores the
+ -x option. */
+static boolean
+xcoff_is_local_label_name (abfd, name)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ const char *name ATTRIBUTE_UNUSED;
+{
+ return false;
+}
+\f
/* The XCOFF reloc table. Actually, XCOFF relocations specify the
bitsize and whether they are signed or not, along with a
conventional type. This table is for the types, which are used for
different algorithms for putting in the reloc. Many of these
relocs need special_function entries, which I have not written. */
-static reloc_howto_type rs6000coff_howto_table[] =
+static reloc_howto_type xcoff_howto_table[] =
{
/* Standard 32 bit relocation. */
HOWTO (0, /* type */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
+ complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_TOC", /* name */
true, /* partial_inplace */
0xffff, /* dst_mask */
false), /* pcrel_offset */
- { 7 },
+ EMPTY_HOWTO (7),
/* Non modifiable absolute branch. */
HOWTO (8, /* type */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
- { 9 },
+ EMPTY_HOWTO (9),
/* Non modifiable relative branch. */
HOWTO (0xa, /* type */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
- { 0xb },
+ EMPTY_HOWTO (0xb),
/* Indirect load. */
HOWTO (0xc, /* type */
0xffff, /* dst_mask */
false), /* pcrel_offset */
- { 0xe },
+ EMPTY_HOWTO (0xe),
/* Non-relocating reference. */
HOWTO (0xf, /* type */
0, /* dst_mask */
false), /* pcrel_offset */
- { 0x10 },
- { 0x11 },
+ EMPTY_HOWTO (0x10),
+ EMPTY_HOWTO (0x11),
/* TOC relative indirect load. */
HOWTO (0x12, /* type */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_REL", /* name */
+ "R_CREL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
- "R_REL", /* name */
+ "R_RBR", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_REL", /* name */
+ "R_RBRC", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false) /* pcrel_offset */
};
-#define RTYPE2HOWTO(cache_ptr, dst) rs6000coff_rtype2howto (cache_ptr, dst)
-
-static void rs6000coff_rtype2howto PARAMS ((arelent *,
- struct internal_reloc *));
-
static void
-rs6000coff_rtype2howto (relent, internal)
+xcoff_rtype2howto (relent, internal)
arelent *relent;
struct internal_reloc *internal;
{
- relent->howto = rs6000coff_howto_table + internal->r_type;
+ relent->howto = xcoff_howto_table + internal->r_type;
/* The r_size field of an XCOFF reloc encodes the bitsize of the
relocation, as well as indicating whether it is signed or not.
#endif
}
-#define coff_bfd_reloc_type_lookup rs6000coff_reloc_type_lookup
-
-static reloc_howto_type *rs6000coff_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-
static reloc_howto_type *
-rs6000coff_reloc_type_lookup (abfd, code)
- bfd *abfd;
+xcoff_reloc_type_lookup (abfd, code)
+ bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
switch (code)
{
case BFD_RELOC_PPC_B26:
- return &rs6000coff_howto_table[0xa];
+ return &xcoff_howto_table[0xa];
case BFD_RELOC_PPC_BA26:
- return &rs6000coff_howto_table[8];
+ return &xcoff_howto_table[8];
case BFD_RELOC_PPC_TOC16:
- return &rs6000coff_howto_table[3];
+ return &xcoff_howto_table[3];
case BFD_RELOC_32:
- return &rs6000coff_howto_table[0];
+ case BFD_RELOC_CTOR:
+ return &xcoff_howto_table[0];
default:
return NULL;
}
: 0) \
| (howto->bitsize - 1)); \
}
+\f
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
#define COFF_LONG_FILENAMES
+#define RTYPE2HOWTO(cache_ptr, dst) xcoff_rtype2howto (cache_ptr, dst)
+
+#define coff_mkobject xcoff_mkobject
+#define coff_bfd_copy_private_bfd_data xcoff_copy_private_bfd_data
+#define coff_bfd_is_local_label_name xcoff_is_local_label_name
+#define coff_bfd_reloc_type_lookup xcoff_reloc_type_lookup
+#define coff_relocate_section _bfd_ppc_xcoff_relocate_section
+
#include "coffcode.h"
\f
/* XCOFF archive support. The original version of this code was by
bfd_false)
#define xcoff_truncate_arname bfd_dont_truncate_arname
+/* We can use the standard get_elt_at_index routine. */
+
+#define xcoff_get_elt_at_index _bfd_generic_get_elt_at_index
+
/* XCOFF archives do not have a timestamp. */
#define xcoff_update_armap_timestamp bfd_true
sz = strtol (hdr.size, (char **) NULL, 10);
contents = (bfd_byte *) bfd_alloc (abfd, sz);
if (contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
if (bfd_read ((PTR) contents, 1, sz, abfd) != sz)
return false;
bfd_ardata (abfd)->symdefs = ((carsym *)
bfd_alloc (abfd, c * sizeof (carsym)));
if (bfd_ardata (abfd)->symdefs == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* After the count comes a list of four byte file offsets. */
for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 4;
(struct artdata *) bfd_zalloc (abfd, sizeof (struct artdata));
if (bfd_ardata (abfd) == (struct artdata *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
(char **) NULL, 10);
bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, SIZEOF_AR_FILE_HDR);
if (bfd_ardata (abfd)->tdata == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR);
return NULL;
namlen = strtol (hdr.namlen, (char **) NULL, 10);
- hdrp = bfd_alloc (abfd, SIZEOF_AR_HDR + namlen + 1);
+ hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd, SIZEOF_AR_HDR + namlen + 1);
if (hdrp == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
memcpy (hdrp, &hdr, SIZEOF_AR_HDR);
if (bfd_read ((char *) hdrp + SIZEOF_AR_HDR, 1, namlen, abfd) != namlen)
return NULL;
ret = (struct areltdata *) bfd_alloc (abfd, sizeof (struct areltdata));
if (ret == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
ret->arch_header = (char *) hdrp;
ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
ret->filename = (char *) hdrp + SIZEOF_AR_HDR;
/* Stat an element in an XCOFF archive. */
-int
+static int
xcoff_generic_stat_arch_elt (abfd, s)
bfd *abfd;
struct stat *s;
static boolean
xcoff_write_armap (abfd, elength, map, orl_count, stridx)
bfd *abfd;
- unsigned int elength;
+ unsigned int elength ATTRIBUTE_UNUSED;
struct orl *map;
unsigned int orl_count;
int stridx;
{
struct xcoff_ar_hdr hdr;
char *p;
- char buf[4];
+ unsigned char buf[4];
bfd *sub;
file_ptr fileoff;
unsigned int i;
}
offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
if (offsets == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
if (bfd_seek (abfd, SIZEOF_AR_FILE_HDR, SEEK_SET) != 0)
return false;
if (stat (bfd_get_filename (sub), &s) != 0)
{
bfd_set_error (bfd_error_system_call);
- return NULL;
+ return false;
}
sprintf (ahdrp->size, "%ld", (long) s.st_size);
if (sub->arelt_data == NULL)
{
- sub->arelt_data = ((struct areltdata *)
- bfd_alloc (sub, sizeof (struct areltdata)));
+ sub->arelt_data = bfd_alloc (sub, sizeof (struct areltdata));
if (sub->arelt_data == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
}
arch_eltdata (sub)->parsed_size = s.st_size;
return true;
}
\f
+/* We can't use the usual coff_sizeof_headers routine, because AIX
+ always uses an a.out header. */
+
+/*ARGSUSED*/
+static int
+_bfd_xcoff_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc ATTRIBUTE_UNUSED;
+{
+ int size;
+
+ size = FILHSZ;
+ if (xcoff_data (abfd)->full_aouthdr)
+ size += AOUTSZ;
+ else
+ size += SMALL_AOUTSZ;
+ size += abfd->section_count * SCNHSZ;
+ return size;
+}
+\f
#define CORE_FILE_P _bfd_dummy_target
#define coff_core_file_failing_command _bfd_nocore_core_file_failing_command
#endif /* LYNX_CORE */
+#define _bfd_xcoff_bfd_get_relocated_section_contents \
+ coff_bfd_get_relocated_section_contents
+#define _bfd_xcoff_bfd_relax_section coff_bfd_relax_section
+#define _bfd_xcoff_bfd_gc_sections coff_bfd_gc_sections
+#define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
+
/* The transfer vector that leads the outside world to all of the above. */
-const bfd_target rs6000coff_vec =
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ rs6000coff_vec =
+#endif
{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
"aixcoff-rs6000", /* name */
+#endif
bfd_target_coff_flavour,
- true, /* data byte order is big */
- true, /* header byte order is big */
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
(HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
+ HAS_LINENO | HAS_DEBUG | DYNAMIC |
HAS_SYMS | HAS_LOCALS | WP_TEXT),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
BFD_JUMP_TABLE_SYMBOLS (coff),
BFD_JUMP_TABLE_RELOCS (coff),
BFD_JUMP_TABLE_WRITE (coff),
- BFD_JUMP_TABLE_LINK (coff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+ BFD_JUMP_TABLE_LINK (_bfd_xcoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_xcoff),
- COFF_SWAP_TABLE,
+ NULL,
+
+ COFF_SWAP_TABLE
};