summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorTom Rix <trix@redhat.com>2001-05-24 20:50:50 +0000
committerTom Rix <trix@redhat.com>2001-05-24 20:50:50 +0000
commitd80dd5ef75967f20a4a44757ffa72aa3ab54b6da (patch)
treebf3e0462976ab0725c57a4c8223141c351afc39b /bfd
parent0ef983d4125db2846ca1b0c971789ce76d42a806 (diff)
downloadgdb-d80dd5ef75967f20a4a44757ffa72aa3ab54b6da.tar.gz
Support for xcoff64
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog49
-rw-r--r--bfd/Makefile.am11
-rw-r--r--bfd/Makefile.in16
-rw-r--r--bfd/bfd-in.h2
-rw-r--r--bfd/coff-rs6000.c1562
-rw-r--r--bfd/coff64-rs6000.c2064
-rw-r--r--bfd/coffcode.h39
-rw-r--r--bfd/coffgen.c51
-rw-r--r--bfd/coffswap.h1
-rw-r--r--bfd/config.bfd4
-rw-r--r--bfd/libbfd.c2
-rw-r--r--bfd/libcoff-in.h4
-rw-r--r--bfd/libcoff.h18
-rw-r--r--bfd/libxcoff.h266
-rw-r--r--bfd/xcofflink.c3427
15 files changed, 5071 insertions, 2445 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f0b42520a5b..d33bf79162d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,52 @@
+2001-05-24 Tom Rix <trix@redhat.com>
+
+ * Makefile.am coff-pmac bfd now defined in coff-rs6000.c
+ xcoff-target.h not used to define rs6000 or ppc bfd.
+ * Makefile.in same
+
+ * bfd-in.h : (struct lineno_cache_entry) promote element "offset"
+ to 64 bit.
+
+ * coff-rs6000.c : Many changes for 64 bit support. Move common
+ 32/64 code to xcofflink.c. Explictly define the rs6000coff_vec
+ and pmac_xcoff_vec
+
+ * coff64-rs6000.c : Many changes for 64 bit support. 64 bit
+ linker now supported. Explictly define the rs6000coff64_vec.
+
+ * coffcode.h : (coff_set_arch_mach_hook) xcoff 64 bit support
+ (coff_print_aux) same
+ (coff_write_object_contents) same
+ (coff_slurp_line_table) same
+
+ * coffgen.c : (coff_fix_symbol_name) formatting
+ (coff_mangle_symbols) xcoff 64 bit support
+ (coff_write_symbol) same
+ (coff_write_alien_symbol) same
+ (coff_write_native_symbol) same
+ (coff_write_symbols) same
+ (coff_get_symbol_info) same
+ (bfd_coff_get_syment) same
+ (coff_print_symbol) same
+
+ * config.bfd : add powerpc64-*-aix* target
+
+ * libcoff-in.h : formatting
+
+ * libcoff.h : move xcoff extern declarations to libxcoff.h
+
+ * libxcoff.h : New file
+
+ * xcofflink.c : Many changes for xcoff64 support. Move common
+ structures to include/coff/xcoff.h. Move specific structure to
+ backends coff-rs6000.c and coff64-rs6000.c. Use new backend
+ functions, defined in libxcoff.h, to isolate 32/64 dependencies.
+
+ (bfd_xcoff_size_dynamic_sections) : special __rtinit symbol for
+ aix4.2+ -binitfini.
+
+ (xcoff_build_ldsyms) : handle special __rtinit symbol.
+
2001-05-23 Alexandre Oliva <aoliva@redhat.com>
* elf64-sparc.c (sparc64_elf_slurp_reloc_table): Fix typo
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 903c79ca588..abdd1798201 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -501,7 +501,7 @@ SOURCE_HFILES = \
elfcode.h elfcore.h elflink.h freebsd.h genlink.h go32stub.h \
libaout.h libbfd.h libcoff.h libecoff.h libhppa.h \
libieee.h libnlm.h liboasys.h libpei.h netbsd.h nlm-target.h \
- nlmcode.h nlmswap.h ns32k.h peicode.h som.h vms.h xcoff-target.h
+ nlmcode.h nlmswap.h ns32k.h peicode.h som.h vms.h libxcoff.h xcoff.h
## ... and all .h files which are in the build tree.
BUILD_HFILES = \
@@ -914,9 +914,12 @@ coff-mips.lo: coff-mips.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/coff/internal.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h \
$(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h libcoff.h \
libecoff.h coffswap.h ecoffswap.h
-coff-pmac.lo: coff-pmac.c $(INCDIR)/filenames.h $(INCDIR)/coff/internal.h \
- $(INCDIR)/coff/rs6000.h libcoff.h $(INCDIR)/bfdlink.h \
- xcoff-target.h coffcode.h coffswap.h
+coff-rs6000.lo: coff64-rs6000.c coff-rs6000.c xcofflink.c \
+ $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h \
+ $(INCDIR)/coff/rs6000.h libcoff.h libxcoff.h coffcode.h coffswap.h
+coff64-rs6000.lo: coff64-rs6000.c coff-rs6000.c xcofflink.c \
+ $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h \
+ $(INCDIR)/coff/rs6k64.h libcoff.h libxcoff.h coffcode.h coffswap.h
coff-rs6000.lo: coff-rs6000.c $(INCDIR)/filenames.h \
$(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h libcoff.h \
$(INCDIR)/bfdlink.h xcoff-target.h coffcode.h coffswap.h
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index f175aaf21a3..56c0759a6fa 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -537,7 +537,6 @@ BFD32_BACKENDS_CFILES = \
vms-tir.c \
xcofflink.c
-
# The .o files needed by all of the 64 bit vectors that are configured into
# target_vector in targets.c if configured with --enable-targets=all
# and --enable-64-bit-bfd.
@@ -631,8 +630,7 @@ SOURCE_HFILES = \
elfcode.h elfcore.h elflink.h freebsd.h genlink.h go32stub.h \
libaout.h libbfd.h libcoff.h libecoff.h libhppa.h \
libieee.h libnlm.h liboasys.h libpei.h netbsd.h nlm-target.h \
- nlmcode.h nlmswap.h ns32k.h peicode.h som.h vms.h xcoff-target.h
-
+ nlmcode.h nlmswap.h ns32k.h peicode.h som.h vms.h xcoff.h libxcoff.h
BUILD_HFILES = \
elf32-target.h elf64-target.h targmatch.h
@@ -1452,12 +1450,12 @@ coff-mips.lo: coff-mips.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/coff/internal.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h \
$(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h libcoff.h \
libecoff.h coffswap.h ecoffswap.h
-coff-pmac.lo: coff-pmac.c $(INCDIR)/filenames.h $(INCDIR)/coff/internal.h \
- $(INCDIR)/coff/rs6000.h libcoff.h $(INCDIR)/bfdlink.h \
- xcoff-target.h coffcode.h coffswap.h
-coff-rs6000.lo: coff-rs6000.c $(INCDIR)/filenames.h \
- $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h libcoff.h \
- $(INCDIR)/bfdlink.h xcoff-target.h coffcode.h coffswap.h
+coff-rs6000.lo: coff64-rs6000.c coff-rs6000.c xcofflink.c \
+ $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h \
+ $(INCDIR)/coff/rs6000.h libcoff.h libxcoff.h coffcode.h coffswap.h
+coff64-rs6000.lo: coff64-rs6000.c coff-rs6000.c xcofflink.c \
+ $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h \
+ $(INCDIR)/coff/rs6k64.h libcoff.h libxcoff.h coffcode.h coffswap.h
coff-sh.lo: coff-sh.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/coff/sh.h $(INCDIR)/coff/internal.h libcoff.h \
coffcode.h coffswap.h
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index bb79a15adfe..ca2c748b661 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -298,7 +298,7 @@ typedef struct lineno_cache_entry {
unsigned int line_number; /* Linenumber from start of function*/
union {
struct symbol_cache_entry *sym; /* Function name */
- unsigned long offset; /* Offset into section */
+ bfd_vma offset; /* Offset into section */
} u;
} alent;
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index ed47000e184..3108568144d 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -29,13 +29,68 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
+#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
+#include "coff/xcoff.h"
#include "coff/rs6000.h"
#include "libcoff.h"
-#define TARGET_NAME "aixcoff-rs6000"
-#define TARGET_SYM rs6000coff_vec
-#include "xcoff-target.h"
+#include "libxcoff.h"
+
+extern const bfd_target * rs6000coff_core_p ();
+extern boolean rs6000coff_core_file_matches_executable_p ();
+extern char *rs6000coff_core_file_failing_command PARAMS ((bfd *abfd));
+extern int rs6000coff_core_file_failing_signal PARAMS ((bfd *abfd));
+extern boolean _bfd_xcoff_mkobject PARAMS ((bfd *));
+extern boolean _bfd_xcoff_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+extern boolean _bfd_xcoff_is_local_label_name PARAMS ((bfd *, const char *));
+extern reloc_howto_type *_bfd_xcoff_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+extern boolean _bfd_xcoff_slurp_armap PARAMS ((bfd *));
+extern const bfd_target *_bfd_xcoff_archive_p PARAMS ((bfd *));
+extern PTR _bfd_xcoff_read_ar_hdr PARAMS ((bfd *));
+extern bfd *_bfd_xcoff_openr_next_archived_file PARAMS ((bfd *, bfd *));
+extern int _bfd_xcoff_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+extern boolean _bfd_xcoff_write_armap
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+extern boolean _bfd_xcoff_write_archive_contents PARAMS ((bfd *));
+extern int _bfd_xcoff_sizeof_headers PARAMS ((bfd *, boolean));
+extern void _bfd_xcoff_swap_sym_in PARAMS ((bfd *, PTR, PTR));
+extern unsigned int _bfd_xcoff_swap_sym_out PARAMS ((bfd *, PTR, PTR));
+extern void _bfd_xcoff_swap_aux_in PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+extern unsigned int _bfd_xcoff_swap_aux_out PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+
+/* Forward declare _bfd_xcoff_rtype2howto for coffcode.h macro */
+void _bfd_xcoff_rtype2howto PARAMS ((arelent *, struct internal_reloc *));
+
+/* coffcode.h needs these to be defined */
+#define RS6000COFF_C 1
+
+#define SELECT_RELOC(internal, howto) \
+ { \
+ internal.r_type = howto->type; \
+ internal.r_size = \
+ ((howto->complain_on_overflow == complain_overflow_signed \
+ ? 0x80 \
+ : 0) \
+ | (howto->bitsize - 1)); \
+ }
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+#define COFF_LONG_FILENAMES
+#define NO_COFF_SYMBOLS
+#define RTYPE2HOWTO(cache_ptr, dst) _bfd_xcoff_rtype2howto (cache_ptr, dst)
+#define coff_mkobject _bfd_xcoff_mkobject
+#define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
+#define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
+#define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup
+#define CORE_FILE_P rs6000coff_core_p
+#define coff_SWAP_sym_in _bfd_xcoff_swap_sym_in
+#define coff_SWAP_sym_out _bfd_xcoff_swap_sym_out
+#define coff_SWAP_aux_in _bfd_xcoff_swap_aux_in
+#define coff_SWAP_aux_out _bfd_xcoff_swap_aux_out
+
+#include "coffcode.h"
/* The main body of code is in coffcode.h. */
@@ -70,6 +125,9 @@ _bfd_xcoff_mkobject (abfd)
xcoff_data (abfd)->csects = NULL;
xcoff_data (abfd)->debug_indices = NULL;
+ /* text section alignment is different than the default */
+ /* xcoff_data (abfd)->text_align_power = 5; */
+
return true;
}
@@ -131,6 +189,8 @@ _bfd_xcoff_is_local_label_name (abfd, name)
return false;
}
+
+
void
_bfd_xcoff_swap_sym_in (abfd, ext1, in1)
bfd *abfd;
@@ -140,18 +200,15 @@ _bfd_xcoff_swap_sym_in (abfd, ext1, in1)
SYMENT *ext = (SYMENT *)ext1;
struct internal_syment *in = (struct internal_syment *)in1;
- if (ext->e.e_name[0] != 0)
- {
- memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
- }
- else
- {
- in->_n._n_n._n_zeroes = 0;
- in->_n._n_n._n_offset =
- bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
- }
+ if(ext->e.e_name[0] != 0) {
+ memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
+ } else {
+ in->_n._n_n._n_zeroes = 0;
+ in->_n._n_n._n_offset =
+ bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
+ }
- in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value);
+ in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value);
in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
in->n_sclass = bfd_h_get_8(abfd, ext->e_sclass);
@@ -167,16 +224,13 @@ _bfd_xcoff_swap_sym_out (abfd, inp, extp)
struct internal_syment *in = (struct internal_syment *)inp;
SYMENT *ext =(SYMENT *)extp;
- if (in->_n._n_name[0] != 0)
- {
- memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
- }
- else
- {
- bfd_h_put_32(abfd, 0, (bfd_byte *) ext->e.e.e_zeroes);
- bfd_h_put_32(abfd, in->_n._n_n._n_offset,
- (bfd_byte *) ext->e.e.e_offset);
- }
+ if(in->_n._n_name[0] != 0) {
+ memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
+ } else {
+ bfd_h_put_32(abfd, 0, (bfd_byte *) ext->e.e.e_zeroes);
+ bfd_h_put_32(abfd, in->_n._n_n._n_offset,
+ (bfd_byte *) ext->e.e.e_offset);
+ }
bfd_h_put_32(abfd, in->n_value , (bfd_byte *) ext->e_value);
bfd_h_put_16(abfd, in->n_scnum , (bfd_byte *) ext->e_scnum);
@@ -210,7 +264,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
case C_FILE:
if (ext->x_file.x_fname[0] == 0) {
in->x_file.x_n.x_zeroes = 0;
- in->x_file.x_n.x_offset =
+ in->x_file.x_n.x_offset =
bfd_h_get_32(abfd, (bfd_byte *) ext->x_file.x_n.x_offset);
} else {
if (numaux > 1)
@@ -231,7 +285,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
case C_HIDEXT:
if (indx + 1 == numaux)
{
- in->x_csect.x_scnlen.l =
+ in->x_csect.x_scnlen.l =
bfd_h_get_32 (abfd, ext->x_csect.x_scnlen);
in->x_csect.x_parmhash = bfd_h_get_32 (abfd,
ext->x_csect.x_parmhash);
@@ -251,11 +305,11 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
case C_LEAFSTAT:
case C_HIDDEN:
if (type == T_NULL) {
- in->x_scn.x_scnlen = bfd_h_get_32(abfd,
+ in->x_scn.x_scnlen = bfd_h_get_32(abfd,
(bfd_byte *) ext->x_scn.x_scnlen);
- in->x_scn.x_nreloc = bfd_h_get_16(abfd,
+ in->x_scn.x_nreloc = bfd_h_get_16(abfd,
(bfd_byte *) ext->x_scn.x_nreloc);
- in->x_scn.x_nlinno = bfd_h_get_16(abfd,
+ in->x_scn.x_nlinno = bfd_h_get_16(abfd,
(bfd_byte *) ext->x_scn.x_nlinno);
/* PE defines some extra fields; we zero them out for
safety. */
@@ -301,10 +355,12 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
end: ;
/* the semicolon is because MSVC doesn't like labels at
- end of block. */
+ end of block. */
}
+
+
unsigned int
_bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
bfd *abfd;
@@ -371,9 +427,9 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
{
- bfd_h_put_32(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
+ bfd_h_put_32(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
(bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
- PUTWORD(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
+ PUTWORD(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
(bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx);
}
else
@@ -393,15 +449,17 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
(bfd_byte *) ext->x_sym.x_misc.x_fsize);
else
{
- bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
+ bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
(bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_lnno);
- bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_size,
+ bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_size,
(bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_size);
}
end:
return bfd_coff_auxesz (abfd);
}
+
+
/* The XCOFF reloc table. Actually, XCOFF relocations specify the
bitsize and whether they are signed or not, along with a
@@ -409,9 +467,6 @@ end:
different algorithms for putting in the reloc. Many of these
relocs need special_function entries, which I have not written. */
-/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
- from smaller values. Start with zero, widen, *then* decrement. */
-#define MINUS_ONE (((bfd_vma)0) - 1)
reloc_howto_type xcoff_howto_table[] =
{
@@ -755,6 +810,7 @@ reloc_howto_type xcoff_howto_table[] =
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
+
HOWTO (0, /* type */
0, /* rightshift */
4, /* size (0 = byte, 1 = short, 2 = long) */
@@ -771,55 +827,6 @@ reloc_howto_type xcoff_howto_table[] =
};
-/* These are the first two like the above but for 16-bit relocs. */
-static reloc_howto_type xcoff_howto_table_16[] =
-{
- /* Standard 16 bit relocation. */
- HOWTO (0, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "R_POS_16", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit relocation, but store negative value. */
- HOWTO (1, /* type */
- 0, /* rightshift */
- -2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "R_NEG_16", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit PC relative relocation. */
- HOWTO (2, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- 0, /* special_function */
- "R_REL_16", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false) /* pcrel_offset */
- };
-
void
_bfd_xcoff_rtype2howto (relent, internal)
arelent *relent;
@@ -827,10 +834,12 @@ _bfd_xcoff_rtype2howto (relent, internal)
{
relent->howto = xcoff_howto_table + internal->r_type;
- if (relent->howto->bitsize != ((unsigned int) internal->r_size & 0x1f) + 1
- && (internal->r_type
- < sizeof (xcoff_howto_table_16)/sizeof (xcoff_howto_table_16[0])))
- relent->howto = xcoff_howto_table_16 + internal->r_type;
+ /* Check for relocs we don't know of. */
+ if (internal->r_type
+ >= sizeof (xcoff_howto_table) / sizeof (xcoff_howto_table[0]))
+ abort ();
+ if (internal->r_type != relent->howto->type)
+ abort ();
/* The r_size field of an XCOFF reloc encodes the bitsize of the
relocation, as well as indicating whether it is signed or not.
@@ -838,7 +847,7 @@ _bfd_xcoff_rtype2howto (relent, internal)
type matches this information. The bitsize is not significant
for R_REF relocs. */
if (relent->howto->dst_mask != 0
- && (relent->howto->bitsize
+ && (relent->howto->bitsize
!= ((unsigned int) internal->r_size & 0x3f) + 1))
abort ();
#if 0
@@ -871,6 +880,7 @@ _bfd_xcoff_reloc_type_lookup (abfd, code)
return NULL;
}
}
+
/* XCOFF archive support. The original version of this code was by
Damon A. Permezel. It was enhanced to permit cross support, and
@@ -917,168 +927,7 @@ _bfd_xcoff_reloc_type_lookup (abfd, code)
/* XCOFF archives use this as a magic string. Note that both strings
have the same length. */
-#define XCOFFARMAG "<aiaff>\012"
-#define XCOFFARMAGBIG "<bigaf>\012"
-#define SXCOFFARMAG 8
-/* This terminates an XCOFF archive member name. */
-
-#define XCOFFARFMAG "`\012"
-#define SXCOFFARFMAG 2
-
-/* XCOFF archives start with this (printable) structure. */
-
-struct xcoff_ar_file_hdr
-{
- /* Magic string. */
- char magic[SXCOFFARMAG];
-
- /* Offset of the member table (decimal ASCII string). */
- char memoff[12];
-
- /* Offset of the global symbol table (decimal ASCII string). */
- char symoff[12];
-
- /* Offset of the first member in the archive (decimal ASCII string). */
- char firstmemoff[12];
-
- /* Offset of the last member in the archive (decimal ASCII string). */
- char lastmemoff[12];
-
- /* Offset of the first member on the free list (decimal ASCII
- string). */
- char freeoff[12];
-};
-
-#define SIZEOF_AR_FILE_HDR (5 * 12 + SXCOFFARMAG)
-
-/* This is the equivalent data structure for the big archive format. */
-
-struct xcoff_ar_file_hdr_big
-{
- /* Magic string. */
- char magic[SXCOFFARMAG];
-
- /* Offset of the member table (decimal ASCII string). */
- char memoff[20];
-
- /* Offset of the global symbol table for 32-bit objects (decimal ASCII
- string). */
- char symoff[20];
-
- /* Offset of the global symbol table for 64-bit objects (decimal ASCII
- string). */
- char symoff64[20];
-
- /* Offset of the first member in the archive (decimal ASCII string). */
- char firstmemoff[20];
-
- /* Offset of the last member in the archive (decimal ASCII string). */
- char lastmemoff[20];
-
- /* Offset of the first member on the free list (decimal ASCII
- string). */
- char freeoff[20];
-};
-
-#define SIZEOF_AR_FILE_HDR_BIG (6 * 20 + SXCOFFARMAG)
-
-/* Each XCOFF archive member starts with this (printable) structure. */
-
-struct xcoff_ar_hdr
-{
- /* File size not including the header (decimal ASCII string). */
- char size[12];
-
- /* File offset of next archive member (decimal ASCII string). */
- char nextoff[12];
-
- /* File offset of previous archive member (decimal ASCII string). */
- char prevoff[12];
-
- /* File mtime (decimal ASCII string). */
- char date[12];
-
- /* File UID (decimal ASCII string). */
- char uid[12];
-
- /* File GID (decimal ASCII string). */
- char gid[12];
-
- /* File mode (octal ASCII string). */
- char mode[12];
-
- /* Length of file name (decimal ASCII string). */
- char 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. */
-};
-
-#define SIZEOF_AR_HDR (7 * 12 + 4)
-
-/* The equivalent for the big archive format. */
-
-struct xcoff_ar_hdr_big
-{
- /* File size not including the header (decimal ASCII string). */
- char size[20];
-
- /* File offset of next archive member (decimal ASCII string). */
- char nextoff[20];
-
- /* File offset of previous archive member (decimal ASCII string). */
- char prevoff[20];
-
- /* File mtime (decimal ASCII string). */
- char date[12];
-
- /* File UID (decimal ASCII string). */
- char uid[12];
-
- /* File GID (decimal ASCII string). */
- char gid[12];
-
- /* File mode (octal ASCII string). */
- char mode[12];
-
- /* Length of file name (decimal ASCII string). */
- char 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. */
-};
-
-#define SIZEOF_AR_HDR_BIG (3 * 20 + 4 * 12 + 4)
-
-/* We often have to distinguish between the old and big file format.
- Make it a bit cleaner. We can use `xcoff_ardata' here because the
- `hdr' member has the same size and position in both formats. */
-#define xcoff_big_format_p(abfd) \
- (xcoff_ardata (abfd)->magic[1] == 'b')
-
-/* We store a copy of the xcoff_ar_file_hdr in the tdata field of the
- artdata structure. Similar for the big archive. */
-#define xcoff_ardata(abfd) \
- ((struct xcoff_ar_file_hdr *) bfd_ardata (abfd)->tdata)
-#define xcoff_ardata_big(abfd) \
- ((struct xcoff_ar_file_hdr_big *) bfd_ardata (abfd)->tdata)
-
-/* We store a copy of the xcoff_ar_hdr in the arelt_data field of an
- archive element. Similar for the big archive. */
-#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
-#define arch_xhdr(bfd) \
- ((struct xcoff_ar_hdr *) arch_eltdata (bfd)->arch_header)
-#define arch_xhdr_big(bfd) \
- ((struct xcoff_ar_hdr_big *) arch_eltdata (bfd)->arch_header)
/* Read in the armap of an XCOFF archive. */
@@ -1135,18 +984,18 @@ _bfd_xcoff_slurp_armap (abfd)
/* The symbol table starts with a four byte count. */
c = bfd_h_get_32 (abfd, contents);
-
+
if (c * 4 >= sz)
{
bfd_set_error (bfd_error_bad_value);
return false;
}
-
+
bfd_ardata (abfd)->symdefs = ((carsym *)
bfd_alloc (abfd, c * sizeof (carsym)));
if (bfd_ardata (abfd)->symdefs == NULL)
return false;
-
+
/* After the count comes a list of four byte file offsets. */
for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 4;
i < c;
@@ -1198,12 +1047,12 @@ _bfd_xcoff_slurp_armap (abfd)
bfd_set_error (bfd_error_bad_value);
return false;
}
-
+
bfd_ardata (abfd)->symdefs = ((carsym *)
bfd_alloc (abfd, c * sizeof (carsym)));
if (bfd_ardata (abfd)->symdefs == NULL)
return false;
-
+
/* After the count comes a list of eight byte file offsets. */
for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8;
i < c;
@@ -1540,6 +1389,7 @@ normalize_filename (abfd)
/* Write out an XCOFF armap. */
+/*ARGSUSED*/
static boolean
xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
bfd *abfd;
@@ -1641,9 +1491,9 @@ xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
struct xcoff_ar_hdr_big hdr;
char *p;
unsigned char buf[4];
- const bfd_arch_info_type *arch_info = NULL;
bfd *sub;
file_ptr fileoff;
+ const bfd_arch_info_type *arch_info;
bfd *object_bfd;
unsigned int i;
@@ -1652,11 +1502,14 @@ xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
machines) since the fields's width is 20 and there numbers with
more than 32 bits can be represented. */
sprintf (hdr.size, "%ld", (long) (4 + orl_ccount * 4 + stridx));
- if (bits64)
+ if (bits64) {
sprintf (hdr.nextoff, "%d", 0);
- else
- sprintf (hdr.nextoff, "%ld", (strtol (prevoff, (char **) NULL, 10)
- + 4 + orl_ccount * 4 + stridx));
+ } else {
+ /* do explict cast to long to remove compiler warning */
+ sprintf (hdr.nextoff, "%ld", (strtol (prevoff, (char **) NULL, 10)
+ + (long) (4 + orl_ccount * 4 + stridx)));
+ }
+
memcpy (hdr.prevoff, prevoff, sizeof (hdr.prevoff));
sprintf (hdr.date, "%d", 0);
sprintf (hdr.uid, "%d", 0);
@@ -1717,8 +1570,7 @@ xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
if (ob != object_bfd)
arch_info = bfd_get_arch_info (ob);
-
- if (arch_info && (arch_info->bits_per_address == 64) != bits64)
+ if ((arch_info->bits_per_address == 64) != bits64)
continue;
name = *map[i].name;
@@ -1739,6 +1591,7 @@ xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
return true;
}
+/*ARGSUSED*/
static boolean
xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
bfd *abfd;
@@ -1750,7 +1603,7 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
unsigned int i;
unsigned int orl_count_32, orl_count_64;
unsigned int stridx_32, stridx_64;
- const bfd_arch_info_type *arch_info = NULL;
+ const bfd_arch_info_type *arch_info;
bfd *object_bfd;
/* First, we look through the symbols and work out which are
@@ -1767,7 +1620,7 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
if (ob != object_bfd)
arch_info = bfd_get_arch_info (ob);
len = strlen (*map[i].name) + 1;
- if (arch_info && arch_info->bits_per_address == 64)
+ if (arch_info->bits_per_address == 64)
{
orl_count_64++;
stridx_64 += len;
@@ -1779,13 +1632,14 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
}
object_bfd = ob;
}
- /* A quick sanity check... */
+ /* A quick sanity check... */
BFD_ASSERT (orl_count_64 + orl_count_32 == orl_count);
- BFD_ASSERT (stridx_64 + stridx_32 == stridx);
+ /* explicit cast to int for compiler */
+ BFD_ASSERT ((int)(stridx_64 + stridx_32) == stridx);
/* Now write out each map. */
if (! xcoff_write_one_armap_big (abfd, map, orl_count, orl_count_32,
- stridx_32, false,
+ stridx_32, false,
xcoff_ardata_big (abfd)->memoff,
xcoff_ardata_big (abfd)->symoff))
return false;
@@ -1794,10 +1648,11 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
xcoff_ardata_big (abfd)->symoff,
xcoff_ardata_big (abfd)->symoff64))
return false;
-
+
return true;
}
+/*ARGSUSED*/
boolean
_bfd_xcoff_write_armap (abfd, elength, map, orl_count, stridx)
bfd *abfd;
@@ -2341,6 +2196,7 @@ _bfd_xcoff_write_archive_contents (abfd)
/* We can't use the usual coff_sizeof_headers routine, because AIX
always uses an a.out header. */
+/*ARGSUSED*/
int
_bfd_xcoff_sizeof_headers (abfd, reloc)
bfd *abfd;
@@ -2356,3 +2212,1169 @@ _bfd_xcoff_sizeof_headers (abfd, reloc)
size += abfd->section_count * SCNHSZ;
return size;
}
+
+/* Routines to swap information in the XCOFF .loader section. If we
+ ever need to write an XCOFF loader, this stuff will need to be
+ moved to another file shared by the linker (which XCOFF calls the
+ ``binder'') and the loader. */
+
+/* Swap in the ldhdr structure. */
+
+static void
+xcoff_swap_ldhdr_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldhdr *src;
+ struct internal_ldhdr *dst;
+{
+ dst->l_version = bfd_get_32 (abfd, src->l_version);
+ dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
+ dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
+ dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
+ dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
+ dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
+ dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
+ dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
+}
+
+/* Swap out the ldhdr structure. */
+
+static void
+xcoff_swap_ldhdr_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldhdr *src;
+ struct external_ldhdr *dst;
+{
+ bfd_put_32 (abfd, src->l_version, dst->l_version);
+ bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
+ bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
+ bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
+ bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
+ bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
+ bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
+ bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
+}
+
+/* Swap in the ldsym structure. */
+
+static void
+xcoff_swap_ldsym_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldsym *src;
+ struct internal_ldsym *dst;
+{
+ if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0) {
+ memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
+ } else {
+ dst->_l._l_l._l_zeroes = 0;
+ dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
+ }
+ dst->l_value = bfd_get_32 (abfd, src->l_value);
+ dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
+ dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
+ dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
+ dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
+ dst->l_parm = bfd_get_32 (abfd, src->l_parm);
+}
+
+/* Swap out the ldsym structure. */
+
+static void
+xcoff_swap_ldsym_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldsym *src;
+ struct external_ldsym *dst;
+{
+
+ if (src->_l._l_l._l_zeroes != 0)
+ memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
+ else
+ {
+ bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes);
+ bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset);
+ }
+ bfd_put_32 (abfd, src->l_value, dst->l_value);
+ bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
+ bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
+ bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
+ bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
+ bfd_put_32 (abfd, src->l_parm, dst->l_parm);
+}
+
+/* Swap in the ldrel structure. */
+
+static void
+xcoff_swap_ldrel_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldrel *src;
+ struct internal_ldrel *dst;
+{
+ dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
+ dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
+ dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
+ dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
+}
+
+/* Swap out the ldrel structure. */
+
+static void
+xcoff_swap_ldrel_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldrel *src;
+ struct external_ldrel *dst;
+{
+ bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
+ bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
+ bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
+ bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
+}
+
+
+
+/* This is the relocation function for the RS/6000/POWER/PowerPC.
+ This is currently the only processor which uses XCOFF; I hope that
+ will never change. */
+
+boolean
+xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
+ input_section, contents, relocs, syms,
+ sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct xcoff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ struct reloc_howto_struct howto;
+ bfd_reloc_status_type rstat;
+
+ /* Relocation type R_REF is a special relocation type which is
+ merely used to prevent garbage collection from occurring for
+ the csect including the symbol which it references. */
+ if (rel->r_type == R_REF)
+ continue;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ addend = 0;
+ }
+ else
+ {
+ h = obj_xcoff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ addend = - sym->n_value;
+
+ }
+
+ /* We build the howto information on the fly. */
+
+ howto.type = rel->r_type;
+ howto.rightshift = 0;
+ howto.size = 2;
+ howto.bitsize = (rel->r_size & 0x1f) + 1;
+ howto.pc_relative = false;
+ howto.bitpos = 0;
+ if ((rel->r_size & 0x80) != 0)
+ howto.complain_on_overflow = complain_overflow_signed;
+ else
+ howto.complain_on_overflow = complain_overflow_bitfield;
+ howto.special_function = NULL;
+ howto.name = "internal";
+ howto.partial_inplace = true;
+ if (howto.bitsize == 32)
+ howto.src_mask = howto.dst_mask = 0xffffffff;
+ else
+ {
+ howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
+ if (howto.bitsize == 16)
+ howto.size = 1;
+ }
+ howto.pcrel_offset = false;
+
+ val = 0;
+
+ if (h == NULL)
+ {
+ asection *sec;
+
+ if (symndx == -1)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = sections[symndx];
+ /* Hack to make sure we use the right TOC anchor value
+ if this reloc is against the TOC anchor. */
+
+ if (sec->name[3] == '0'
+ && strcmp (sec->name, ".tc0") == 0) {
+
+ val = xcoff_data (output_bfd)->toc;
+ } else {
+
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_common)
+ {
+ asection *sec;
+
+ sec = h->root.u.c.p->section;
+ val = (sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
+ || (h->flags & XCOFF_IMPORT) != 0)
+ {
+ /* Every symbol in a shared object is defined somewhere. */
+ val = 0;
+ }
+ else if (! info->relocateable)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma, true)))
+ return false;
+
+ /* Don't try to process the reloc. It can't help, and
+ it may generate another error. */
+ continue;
+ }
+ }
+
+ /* I took the relocation type definitions from two documents:
+ the PowerPC AIX Version 4 Application Binary Interface, First
+ Edition (April 1992), and the PowerOpen ABI, Big-Endian
+ 32-Bit Hardware Implementation (June 30, 1994). Differences
+ between the documents are noted below. */
+
+ switch (rel->r_type)
+ {
+ case R_RTB:
+ case R_RRTBI:
+ case R_RRTBA:
+ /* These relocs are defined by the PowerPC ABI to be
+ relative branches which use half of the difference
+ between the symbol and the program counter. I can't
+ quite figure out when this is useful. These relocs are
+ not defined by the PowerOpen ABI. */
+ default:
+ (*_bfd_error_handler)
+ (_("%s: unsupported relocation type 0x%02x"),
+ bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ case R_POS:
+ /* Simple positive relocation. */
+ break;
+ case R_NEG:
+ /* Simple negative relocation. */
+ val = - val;
+ break;
+ case R_REL:
+ /* Simple PC relative relocation. */
+ howto.pc_relative = true;
+ break;
+ case R_TOC:
+ /* TOC relative relocation. The value in the instruction in
+ the input file is the offset from the input file TOC to
+ the desired location. We want the offset from the final
+ TOC to the desired location. We have:
+ isym = iTOC + in
+ iinsn = in + o
+ osym = oTOC + on
+ oinsn = on + o
+ so we must change insn by on - in.
+ */
+ case R_GL:
+ /* Global linkage relocation. The value of this relocation
+ is the address of the entry in the TOC section. */
+ case R_TCL:
+ /* Local object TOC address. I can't figure out the
+ difference between this and case R_GL. */
+ case R_TRL:
+ /* TOC relative relocation. A TOC relative load instruction
+ which may be changed to a load address instruction.
+ FIXME: We don't currently implement this optimization. */
+ case R_TRLA:
+ /* TOC relative relocation. This is a TOC relative load
+ address instruction which may be changed to a load
+ instruction. FIXME: I don't know if this is the correct
+ implementation. */
+ if (h != NULL && h->smclas != XMC_TD)
+ {
+ if (h->toc_section == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
+ bfd_get_filename (input_bfd), rel->r_vaddr,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ val = (h->toc_section->output_section->vma
+ + h->toc_section->output_offset);
+ }
+
+ val = ((val - xcoff_data (output_bfd)->toc)
+ - (sym->n_value - xcoff_data (input_bfd)->toc));
+ addend = 0;
+ break;
+ case R_BA:
+ /* Absolute branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CAI:
+ /* The PowerPC ABI defines this as an absolute call which
+ may be modified to become a relative call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBA:
+ /* Absolute branch which may be modified to become a
+ relative branch. */
+ case R_RBAC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to an absolute branch
+ to a symbol. The PowerOpen ABI does not define this
+ relocation type. */
+ case R_RBRC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to a relative branch.
+ The PowerOpen ABI does not define this relocation type. */
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ break;
+ case R_BR:
+ /* Relative branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CREL:
+ /* The PowerPC ABI defines this as a relative call which may
+ be modified to become an absolute call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBR:
+ /* A relative branch which may be modified to become an
+ absolute branch. FIXME: We don't implement this,
+ although we should for symbols of storage mapping class
+ XMC_XO. */
+ howto.pc_relative = true;
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ break;
+ case R_RL:
+ /* The PowerPC AIX ABI describes this as a load which may be
+ changed to a load address. The PowerOpen ABI says this
+ is the same as case R_POS. */
+ break;
+ case R_RLA:
+ /* The PowerPC AIX ABI describes this as a load address
+ which may be changed to a load. The PowerOpen ABI says
+ this is the same as R_POS. */
+ break;
+ }
+
+ /* If we see an R_BR or R_RBR reloc which is jumping to global
+ linkage code, and it is followed by an appropriate cror nop
+ instruction, we replace the cror with lwz r2,20(r1). This
+ restores the TOC after the glink code. Contrariwise, if the
+ call is followed by a lwz r2,20(r1), but the call is not
+ going to global linkage code, we can replace the load with a
+ cror. */
+ if ((rel->r_type == R_BR || rel->r_type == R_RBR)
+ && h != NULL
+ && h->root.type == bfd_link_hash_defined
+ && (rel->r_vaddr - input_section->vma + 8
+ <= input_section->_cooked_size))
+ {
+ bfd_byte *pnext;
+ unsigned long next;
+
+ pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+ next = bfd_get_32 (input_bfd, pnext);
+
+ /* The _ptrgl function is magic. It is used by the AIX
+ compiler to call a function through a pointer. */
+ if (h->smclas == XMC_GL
+ || strcmp (h->root.root.string, "._ptrgl") == 0)
+ {
+ if (next == 0x4def7b82 /* cror 15,15,15 */
+ || next == 0x4ffffb82 /* cror 31,31,31 */
+ || next == 0x60000000) /* ori r0,r0,0 */
+ bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */
+ }
+ else
+ {
+ if (next == 0x80410014) /* lwz r1,20(r1) */
+ bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
+ }
+ }
+
+ /* A PC relative reloc includes the section address. */
+ if (howto.pc_relative)
+ addend += input_section->vma;
+
+ rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ char howto_name[10];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+
+ if (name == NULL)
+ return false;
+ }
+ sprintf (howto_name, "0x%02x", rel->r_type);
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto_name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static boolean
+_bfd_xcoff_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct xcoff_loader_info *ldinfo;
+ struct internal_ldsym *ldsym;
+ const char *name;
+{
+ size_t len;
+ len = strlen (name);
+
+ if (len <= SYMNMLEN)
+ strncpy (ldsym->_l._l_name, name, SYMNMLEN);
+ else
+ {
+ if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
+ {
+ size_t newalc;
+ bfd_byte *newstrings;
+
+ newalc = ldinfo->string_alc * 2;
+ if (newalc == 0)
+ newalc = 32;
+ while (ldinfo->string_size + len + 3 > newalc)
+ newalc *= 2;
+
+ newstrings = ((bfd_byte *)
+ bfd_realloc ((PTR) ldinfo->strings, newalc));
+ if (newstrings == NULL)
+ {
+ ldinfo->failed = true;
+ return false;
+ }
+ ldinfo->string_alc = newalc;
+ ldinfo->strings = newstrings;
+ }
+
+ bfd_put_16 (ldinfo->output_bfd, len + 1,
+ ldinfo->strings + ldinfo->string_size);
+ strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
+ ldsym->_l._l_l._l_zeroes = 0;
+ ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
+ ldinfo->string_size += len + 3;
+ }
+
+ return true;
+}
+
+static boolean
+_bfd_xcoff_put_symbol_name (bfd *abfd, struct bfd_strtab_hash *strtab,
+ struct internal_syment *sym,
+ const char *name) {
+
+ if (strlen (name) <= SYMNMLEN) {
+ strncpy (sym->_n._n_name, name, SYMNMLEN);
+ } else {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+ indx = _bfd_stringtab_add (strtab, name, hash, false);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ sym->_n._n_n._n_zeroes = 0;
+ sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+ return true;
+}
+
+static asection *
+xcoff_create_csect_from_smclas (abfd, aux, symbol_name)
+ bfd *abfd;
+ union internal_auxent *aux;
+ char *symbol_name;
+{
+
+ asection *return_value = NULL;
+
+ /*
+ * .sv64 = x_smclas == 17
+ * This is an invalid csect for 32 bit apps.
+ */
+ static const char *names[19] = {
+ ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
+ ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
+ ".td", NULL, ".sv3264"
+ };
+
+ if ((19 >= aux->x_csect.x_smclas) &&
+ (NULL != names[aux->x_csect.x_smclas])) {
+
+ return_value = bfd_make_section_anyway
+ (abfd, names[aux->x_csect.x_smclas]);
+
+
+ } else {
+ (*_bfd_error_handler)
+ (_("%s: symbol `%s' has unrecognized smclas %d"),
+ bfd_get_filename (abfd), symbol_name, aux->x_csect.x_smclas);
+ bfd_set_error (bfd_error_bad_value);
+ }
+
+ return return_value;
+}
+
+boolean
+xcoff_is_lineno_count_overflow (abfd, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_vma value;
+{
+ if (0xffff <= value) {
+ return true;
+ }
+ return false;
+}
+
+boolean
+xcoff_is_reloc_count_overflow (abfd, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_vma value;
+{
+ if (0xffff <= value) {
+ return true;
+ }
+ return false;
+}
+
+bfd_vma
+xcoff_loader_symbol_offset (abfd, ldhdr)
+ bfd *abfd;
+ struct internal_ldhdr *ldhdr ATTRIBUTE_UNUSED;
+{
+ return bfd_xcoff_ldhdrsz(abfd);
+}
+
+bfd_vma
+xcoff_loader_reloc_offset (abfd, ldhdr)
+ bfd *abfd;
+ struct internal_ldhdr *ldhdr;
+{
+ return bfd_xcoff_ldhdrsz(abfd) +
+ (ldhdr->l_nsyms * bfd_xcoff_ldsymsz(abfd));
+}
+
+
+static reloc_howto_type xcoff_dynamic_reloc =
+HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false); /* pcrel_offset */
+
+/*
+ * glink
+ *
+ * The first word of global linkage code must be modified by filling in
+ * the correct TOC offset.
+ */
+static unsigned long xcoff_glink_code[9] =
+{
+ 0x81820000, /* lwz r12,0(r2) */
+ 0x90410014, /* stw r2,20(r1) */
+ 0x800c0000, /* lwz r0,0(r12) */
+ 0x804c0004, /* lwz r2,4(r12) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x4e800420, /* bctr */
+ 0x00000000, /* start of traceback table */
+ 0x000c8000, /* traceback table */
+ 0x00000000, /* traceback table */
+};
+
+
+static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
+{
+ { /* COFF backend, defined in libcoff.h */
+ _bfd_xcoff_swap_aux_in, /* _bfd_coff_swap_aux_in */
+ _bfd_xcoff_swap_sym_in, /* _bfd_coff_swap_sym_in */
+ coff_swap_lineno_in, /* _bfd_coff_swap_lineno_in */
+ _bfd_xcoff_swap_aux_out, /* _bfd_swap_aux_out */
+ _bfd_xcoff_swap_sym_out, /* _bfd_swap_sym_out */
+ coff_swap_lineno_out, /* _bfd_swap_lineno_out */
+ coff_swap_reloc_out, /* _bfd_swap_reloc_out */
+ coff_swap_filehdr_out, /* _bfd_swap_filehdr_out */
+ coff_swap_aouthdr_out, /* _bfd_swap_aouthdr_out */
+ coff_swap_scnhdr_out, /* _bfd_swap_scnhdr_out */
+ FILHSZ, /* _bfd_filhsz */
+ AOUTSZ, /* _bfd_aoutsz */
+ SCNHSZ, /* _bfd_scnhsz */
+ SYMESZ, /* _bfd_symesz */
+ AUXESZ, /* _bfd_auxesz */
+ RELSZ, /* _bfd_relsz */
+ LINESZ, /* _bfd_linesz */
+ FILNMLEN, /* _bfd_filnmlen */
+ true, /* _bfd_coff_long_filenames */
+ false, /* _bfd_coff_long_section_names */
+ (3), /* _bfd_coff_default_section_alignment_power */
+ false, /* _bfd_coff_force_symnames_in_strings */
+ 2, /* _bfd_coff_debug_string_prefix_length */
+ coff_swap_filehdr_in, /* _bfd_coff_swap_filehdr_in */
+ coff_swap_aouthdr_in, /* _bfd_swap_aouthdr_in */
+ coff_swap_scnhdr_in, /* _bfd_swap_scnhdr_in */
+ coff_swap_reloc_in, /* _bfd_reloc_in */
+ coff_bad_format_hook, /* _bfd_bad_format_hook */
+ coff_set_arch_mach_hook, /* _bfd_set_arch_mach_hook */
+ coff_mkobject_hook, /* _bfd_mkobject_hook */
+ styp_to_sec_flags, /* _bfd_syp_to_sec_flags */
+ coff_set_alignment_hook, /* _bfd_set_alignment_hook */
+ coff_slurp_symbol_table, /* _bfd_coff_slurp_symbol_table */
+ symname_in_debug_hook, /* _coff_symname_in_debug_hook */
+ coff_pointerize_aux_hook, /* _bfd_coff_pointerize_aux_hook */
+ coff_print_aux, /* bfd_coff_print_aux */
+ dummy_reloc16_extra_cases, /* _bfd_coff_reloc16_extra_cases */
+ dummy_reloc16_estimate, /* _bfd_coff_reloc16_estimate */
+ NULL, /* bfd_coff_sym_is_global */
+ /* _bfd_coff_compute_section_file_positions */
+ coff_compute_section_file_positions,
+ NULL , /* _bfd_coff_start_final_link */
+ xcoff_ppc_relocate_section, /* _bfd_coff_relocate_section */
+ coff_rtype_to_howto, /* _bfd_coff_rtype_to_howto */
+ NULL , /* _bfd_coff_addust_symndx */
+ _bfd_generic_link_add_one_symbol, /* _bfd_coff_add_one_symbol */
+ coff_link_output_has_begun, /* _bfd_coff_link_output_has_begun */
+ coff_final_link_postscript /* _bfd_coff_final_link_postscript */
+ },
+
+ 0x01DF, /* magic number */
+ bfd_arch_rs6000, /* architecture */
+ bfd_mach_rs6k, /* machine */
+
+
+ /* function pointers to xcoff specific swap routines */
+ xcoff_swap_ldhdr_in, /* _xcoff_swap_ldhdr_in */
+ xcoff_swap_ldhdr_out, /* _xcoff_swap_ldhdr_out */
+ xcoff_swap_ldsym_in, /* _xcoff_swap_ldsym_in */
+ xcoff_swap_ldsym_out, /* _xcoff_swap_ldsym_out */
+ xcoff_swap_ldrel_in, /* _xcoff_swap_ldrel_in */
+ xcoff_swap_ldrel_out, /* _xcoff_swap_ldrel_out */
+
+ /* sizes */
+ LDHDRSZ, /* _xcoff_ldhdrsz */
+ LDSYMSZ, /* _xcoff_ldsymsz */
+ LDRELSZ, /* _xcoff_ldrelsz */
+ 12, /* _xcoff_function_descriptor_size */
+ SMALL_AOUTSZ, /* _xcoff_small_aout_header_size */
+
+ /* versions */
+ 1, /* _xcoff_ldhdr_version */
+
+ /* xcoff vs xcoff64 putting symbol names */
+ _bfd_xcoff_put_symbol_name, /* _xcoff_put_symbol_name */
+ _bfd_xcoff_put_ldsymbol_name, /* _xcoff_put_ldsymbol_name */
+
+ &xcoff_dynamic_reloc, /* dynamic reloc howto */
+
+ xcoff_create_csect_from_smclas, /* _xcoff_create_csect_from_smclas */
+
+ /* lineno and reloc count overflow */
+ xcoff_is_lineno_count_overflow,
+ xcoff_is_reloc_count_overflow,
+
+ xcoff_loader_symbol_offset,
+ xcoff_loader_reloc_offset,
+
+ /* glink */
+ &xcoff_glink_code[0],
+ (36), /* _xcoff_glink_size */
+
+};
+
+/* The transfer vector that leads the outside world to all of the above. */
+const bfd_target rs6000coff_vec =
+{
+ "aixcoff-rs6000",
+ bfd_target_xcoff_flavour,
+ 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 | DYNAMIC |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ /* data */
+ bfd_getb64, /* bfd_getx64 */
+ bfd_getb_signed_64, /* bfd_getx_signed_64 */
+ bfd_putb64, /* bfd_putx64 */
+ bfd_getb32, /* bfd_getx32 */
+ bfd_getb_signed_32, /* bfd_getx_signed_32 */
+ bfd_putb32, /* bfd_putx32 */
+ bfd_getb16, /* bfd_getx16 */
+ bfd_getb_signed_16, /* bfd_getx_signed_16 */
+ bfd_putb16, /* bfd_putx16 */
+
+ /* hdrs */
+ bfd_getb64, /* bfd_h_getx64 */
+ bfd_getb_signed_64, /* bfd_h_getx_signed_64 */
+ bfd_putb64, /* bfd_h_putx64 */
+ bfd_getb32, /* bfd_h_getx32 */
+ bfd_getb_signed_32, /* bfd_h_getx_signed_32 */
+ bfd_putb32, /* bfd_h_putx32 */
+ bfd_getb16, /* bfd_h_getx16 */
+ bfd_getb_signed_16, /* bfd_h_getx_signed_16 */
+ bfd_putb16, /* bfd_h_putx16 */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target,
+ coff_object_p,
+ _bfd_xcoff_archive_p,
+ CORE_FILE_P
+ },
+
+ { /* bfd_set_format */
+ bfd_false,
+ coff_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ {/* bfd_write_contents */
+ bfd_false,
+ coff_write_object_contents,
+ _bfd_xcoff_write_archive_contents,
+ bfd_false
+ },
+
+ /* Generic */
+ bfd_true, /* _close_and_cleanup */
+ bfd_true, /* _bfd_free_cached_info */
+ coff_new_section_hook, /* _new_section_hook */
+ _bfd_generic_get_section_contents, /* _bfd_get_section_contents */
+ /* _bfd_get_section_contents_in_window */
+ _bfd_generic_get_section_contents_in_window,
+
+ /* Copy */
+ _bfd_xcoff_copy_private_bfd_data, /* _bfd_copy_private_bfd */
+ /* _bfd_merge_private_bfd_data */
+ ((boolean (*) (bfd *, bfd *)) bfd_true),
+ /* _bfd_copy_pivate_section_data */
+ ((boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
+ /* _bfd_copy_private_symbol_data */
+ ((boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
+ ((boolean (*) (bfd *, flagword)) bfd_true), /* _bfd_set_private_flags */
+ ((boolean (*) (bfd *, void * )) bfd_true), /* _bfd_print_private_bfd_data */
+
+ /* Core */
+ rs6000coff_core_file_failing_command, /* _core_file_failing_command */
+ rs6000coff_core_file_failing_signal, /* _core_file_failing_signal */
+ /* _core_file_matches_executable_p */
+ rs6000coff_core_file_matches_executable_p,
+
+ /* Archive */
+ _bfd_xcoff_slurp_armap, /* _slurp_armap */
+ /* XCOFF archives do not have
+ anything which corresponds to
+ an extended name table. */
+ bfd_false, /* _slurp_extended_name_table */
+ /* _construct_extended_name_table */
+ ((boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
+ bfd_dont_truncate_arname, /* _truncate_arname */
+ _bfd_xcoff_write_armap, /* _write_armap */
+ _bfd_xcoff_read_ar_hdr, /* _read_ar_hdr */
+ _bfd_xcoff_openr_next_archived_file, /* _openr_next_archived_file */
+ _bfd_generic_get_elt_at_index, /* _get_elt_at_index */
+ _bfd_xcoff_generic_stat_arch_elt, /* _generic_dtat_arch_elt */
+ /* XCOFF archives do not have
+ a timestamp. */
+ bfd_true, /* _update_armap_timestamp */
+
+ /* Symbols */
+ coff_get_symtab_upper_bound, /* _get_symtab_upper_bound */
+ coff_get_symtab, /* _get_symtab */
+ coff_make_empty_symbol, /* _make_empty_symbol */
+ coff_print_symbol, /* _print_symbol */
+ coff_get_symbol_info, /* _get_symbol_info */
+ _bfd_xcoff_is_local_label_name, /* _bfd_is_local_label_name */
+ coff_get_lineno, /* _get_lineno */
+ coff_find_nearest_line, /* _find_nearest_line */
+ coff_bfd_make_debug_symbol, /* _bfd_make_debug_symbol */
+ _bfd_generic_read_minisymbols, /* _read_minisymbols */
+ _bfd_generic_minisymbol_to_symbol, /* _minsymbol_to_symbol */
+
+ /* Reloc */
+ coff_get_reloc_upper_bound, /* _get_reloc_upper_bound */
+ coff_canonicalize_reloc, /* _cononicalize_reloc */
+ _bfd_xcoff_reloc_type_lookup, /* _bfd_reloc_type_lookup */
+
+ /* Write */
+ coff_set_arch_mach, /* _set_arch_mach */
+ coff_set_section_contents, /* _set_section_contents */
+
+ /* Link */
+ _bfd_xcoff_sizeof_headers, /* _sizeof_headers */
+ /* _bfd_get_relocated_section_contents */
+ bfd_generic_get_relocated_section_contents,
+ bfd_generic_relax_section, /* _bfd_relax_section */
+ _bfd_xcoff_bfd_link_hash_table_create, /* _bfd_link_hash_table_create */
+ _bfd_xcoff_bfd_link_add_symbols, /* _bfd_link_add_symbols */
+ _bfd_xcoff_bfd_final_link, /* _bfd_filnal_link */
+ _bfd_generic_link_split_section, /* _bfd_link_split_section */
+ bfd_generic_gc_sections, /* _bfd_gc_sections */
+ bfd_generic_merge_sections, /* _bfd_merge_sections */
+
+ /* Dynamic */
+ /* _get_dynamic_symtab_upper_bound */
+ _bfd_xcoff_get_dynamic_symtab_upper_bound,
+ _bfd_xcoff_canonicalize_dynamic_symtab, /* _cononicalize_dynamic_symtab */
+ _bfd_xcoff_get_dynamic_reloc_upper_bound,/* _get_dynamic_reloc_upper_bound */
+ _bfd_xcoff_canonicalize_dynamic_reloc, /* _cononicalize_dynamic_reloc */
+
+ /* Opposite endian version, none exists */
+ NULL,
+
+ /* back end data */
+ (void *) &bfd_xcoff_backend_data,
+};
+
+/*
+ * xcoff-powermac target
+ * Old target.
+ * Only difference between this target and the rs6000 target is the
+ * the default architecture and machine type used in coffcode.h
+ *
+ * PowerPC Macs use the same magic numbers as RS/6000
+ * (because that's how they were bootstrapped originally),
+ * but they are always PowerPC architecture.
+ */
+static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
+{
+ { /* COFF backend, defined in libcoff.h */
+ _bfd_xcoff_swap_aux_in, /* _bfd_coff_swap_aux_in */
+ _bfd_xcoff_swap_sym_in, /* _bfd_coff_swap_sym_in */
+ coff_swap_lineno_in, /* _bfd_coff_swap_lineno_in */
+ _bfd_xcoff_swap_aux_out, /* _bfd_swap_aux_out */
+ _bfd_xcoff_swap_sym_out, /* _bfd_swap_sym_out */
+ coff_swap_lineno_out, /* _bfd_swap_lineno_out */
+ coff_swap_reloc_out, /* _bfd_swap_reloc_out */
+ coff_swap_filehdr_out, /* _bfd_swap_filehdr_out */
+ coff_swap_aouthdr_out, /* _bfd_swap_aouthdr_out */
+ coff_swap_scnhdr_out, /* _bfd_swap_scnhdr_out */
+ FILHSZ, /* _bfd_filhsz */
+ AOUTSZ, /* _bfd_aoutsz */
+ SCNHSZ, /* _bfd_scnhsz */
+ SYMESZ, /* _bfd_symesz */
+ AUXESZ, /* _bfd_auxesz */
+ RELSZ, /* _bfd_relsz */
+ LINESZ, /* _bfd_linesz */
+ FILNMLEN, /* _bfd_filnmlen */
+ true, /* _bfd_coff_long_filenames */
+ false, /* _bfd_coff_long_section_names */
+ (3), /* _bfd_coff_default_section_alignment_power */
+ false, /* _bfd_coff_force_symnames_in_strings */
+ 2, /* _bfd_coff_debug_string_prefix_length */
+ coff_swap_filehdr_in, /* _bfd_coff_swap_filehdr_in */
+ coff_swap_aouthdr_in, /* _bfd_swap_aouthdr_in */
+ coff_swap_scnhdr_in, /* _bfd_swap_scnhdr_in */
+ coff_swap_reloc_in, /* _bfd_reloc_in */
+ coff_bad_format_hook, /* _bfd_bad_format_hook */
+ coff_set_arch_mach_hook, /* _bfd_set_arch_mach_hook */
+ coff_mkobject_hook, /* _bfd_mkobject_hook */
+ styp_to_sec_flags, /* _bfd_syp_to_sec_flags */
+ coff_set_alignment_hook, /* _bfd_set_alignment_hook */
+ coff_slurp_symbol_table, /* _bfd_coff_slurp_symbol_table */
+ symname_in_debug_hook, /* _coff_symname_in_debug_hook */
+ coff_pointerize_aux_hook, /* _bfd_coff_pointerize_aux_hook */
+ coff_print_aux, /* bfd_coff_print_aux */
+ dummy_reloc16_extra_cases, /* _bfd_coff_reloc16_extra_cases */
+ dummy_reloc16_estimate, /* _bfd_coff_reloc16_estimate */
+ NULL, /* bfd_coff_sym_is_global */
+ /* _bfd_coff_compute_section_file_positions */
+ coff_compute_section_file_positions,
+ NULL , /* _bfd_coff_start_final_link */
+ xcoff_ppc_relocate_section, /* _bfd_coff_relocate_section */
+ coff_rtype_to_howto, /* _bfd_coff_rtype_to_howto */
+ NULL , /* _bfd_coff_addust_symndx */
+ _bfd_generic_link_add_one_symbol, /* _bfd_coff_add_one_symbol */
+ coff_link_output_has_begun, /* _bfd_coff_link_output_has_begun */
+ coff_final_link_postscript /* _bfd_coff_final_link_postscript */
+ },
+
+ 0x01DF, /* magic number */
+ bfd_arch_powerpc, /* architecture */
+ bfd_mach_ppc, /* machine */
+
+ /* function pointers to xcoff specific swap routines */
+ xcoff_swap_ldhdr_in, /* _xcoff_swap_ldhdr_in */
+ xcoff_swap_ldhdr_out, /* _xcoff_swap_ldhdr_out */
+ xcoff_swap_ldsym_in, /* _xcoff_swap_ldsym_in */
+ xcoff_swap_ldsym_out, /* _xcoff_swap_ldsym_out */
+ xcoff_swap_ldrel_in, /* _xcoff_swap_ldrel_in */
+ xcoff_swap_ldrel_out, /* _xcoff_swap_ldrel_out */
+
+ /* sizes */
+ LDHDRSZ, /* _xcoff_ldhdrsz */
+ LDSYMSZ, /* _xcoff_ldsymsz */
+ LDRELSZ, /* _xcoff_ldrelsz */
+ 12, /* _xcoff_function_descriptor_size */
+ SMALL_AOUTSZ, /* _xcoff_small_aout_header_size */
+
+ /* versions */
+ 1, /* _xcoff_ldhdr_version */
+
+ /* xcoff vs xcoff64 putting symbol names */
+ _bfd_xcoff_put_symbol_name, /* _xcoff_put_symbol_name */
+ _bfd_xcoff_put_ldsymbol_name, /* _xcoff_put_ldsymbol_name */
+
+ &xcoff_dynamic_reloc, /* dynamic reloc howto */
+
+ xcoff_create_csect_from_smclas, /* _xcoff_create_csect_from_smclas */
+
+ /* lineno and reloc count overflow */
+ xcoff_is_lineno_count_overflow,
+ xcoff_is_reloc_count_overflow,
+
+ xcoff_loader_symbol_offset,
+ xcoff_loader_reloc_offset,
+
+ /* glink */
+ &xcoff_glink_code[0],
+ (36), /* _xcoff_glink_size */
+
+};
+
+/* The transfer vector that leads the outside world to all of the above. */
+const bfd_target pmac_xcoff_vec =
+{
+ "xcoff-powermac",
+ bfd_target_xcoff_flavour,
+ 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 | DYNAMIC |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ /* data */
+ bfd_getb64, /* bfd_getx64 */
+ bfd_getb_signed_64, /* bfd_getx_signed_64 */
+ bfd_putb64, /* bfd_putx64 */
+ bfd_getb32, /* bfd_getx32 */
+ bfd_getb_signed_32, /* bfd_getx_signed_32 */
+ bfd_putb32, /* bfd_putx32 */
+ bfd_getb16, /* bfd_getx16 */
+ bfd_getb_signed_16, /* bfd_getx_signed_16 */
+ bfd_putb16, /* bfd_putx16 */
+
+ /* hdrs */
+ bfd_getb64, /* bfd_h_getx64 */
+ bfd_getb_signed_64, /* bfd_h_getx_signed_64 */
+ bfd_putb64, /* bfd_h_putx64 */
+ bfd_getb32, /* bfd_h_getx32 */
+ bfd_getb_signed_32, /* bfd_h_getx_signed_32 */
+ bfd_putb32, /* bfd_h_putx32 */
+ bfd_getb16, /* bfd_h_getx16 */
+ bfd_getb_signed_16, /* bfd_h_getx_signed_16 */
+ bfd_putb16, /* bfd_h_putx16 */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target,
+ coff_object_p,
+ _bfd_xcoff_archive_p,
+ CORE_FILE_P
+ },
+
+ { /* bfd_set_format */
+ bfd_false,
+ coff_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ {/* bfd_write_contents */
+ bfd_false,
+ coff_write_object_contents,
+ _bfd_xcoff_write_archive_contents,
+ bfd_false
+ },
+
+ /* Generic */
+ bfd_true, /* _close_and_cleanup */
+ bfd_true, /* _bfd_free_cached_info */
+ coff_new_section_hook, /* _new_section_hook */
+ _bfd_generic_get_section_contents, /* _bfd_get_section_contents */
+ /* _bfd_get_section_contents_in_window */
+ _bfd_generic_get_section_contents_in_window,
+
+ /* Copy */
+ _bfd_xcoff_copy_private_bfd_data, /* _bfd_copy_private_bfd */
+ /* _bfd_merge_private_bfd_data */
+ ((boolean (*) (bfd *, bfd *)) bfd_true),
+ /* _bfd_copy_pivate_section_data */
+ ((boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
+ /* _bfd_copy_private_symbol_data */
+ ((boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
+ ((boolean (*) (bfd *, flagword)) bfd_true), /* _bfd_set_private_flags */
+ ((boolean (*) (bfd *, void * )) bfd_true), /* _bfd_print_private_bfd_data */
+
+ /* Core */
+ rs6000coff_core_file_failing_command, /* _core_file_failing_command */
+ rs6000coff_core_file_failing_signal, /* _core_file_failing_signal */
+ /* _core_file_matches_executable_p */
+ rs6000coff_core_file_matches_executable_p,
+
+ /* Archive */
+ _bfd_xcoff_slurp_armap, /* _slurp_armap */
+ /* XCOFF archives do not have
+ anything which corresponds to
+ an extended name table. */
+ bfd_false, /* _slurp_extended_name_table */
+ /* _construct_extended_name_table */
+ ((boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
+ bfd_dont_truncate_arname, /* _truncate_arname */
+ _bfd_xcoff_write_armap, /* _write_armap */
+ _bfd_xcoff_read_ar_hdr, /* _read_ar_hdr */
+ _bfd_xcoff_openr_next_archived_file, /* _openr_next_archived_file */
+ _bfd_generic_get_elt_at_index, /* _get_elt_at_index */
+ _bfd_xcoff_generic_stat_arch_elt, /* _generic_dtat_arch_elt */
+ /* XCOFF archives do not have
+ a timestamp. */
+ bfd_true, /* _update_armap_timestamp */
+
+ /* Symbols */
+ coff_get_symtab_upper_bound, /* _get_symtab_upper_bound */
+ coff_get_symtab, /* _get_symtab */
+ coff_make_empty_symbol, /* _make_empty_symbol */
+ coff_print_symbol, /* _print_symbol */
+ coff_get_symbol_info, /* _get_symbol_info */
+ _bfd_xcoff_is_local_label_name, /* _bfd_is_local_label_name */
+ coff_get_lineno, /* _get_lineno */
+ coff_find_nearest_line, /* _find_nearest_line */
+ coff_bfd_make_debug_symbol, /* _bfd_make_debug_symbol */
+ _bfd_generic_read_minisymbols, /* _read_minisymbols */
+ _bfd_generic_minisymbol_to_symbol, /* _minsymbol_to_symbol */
+
+ /* Reloc */
+ coff_get_reloc_upper_bound, /* _get_reloc_upper_bound */
+ coff_canonicalize_reloc, /* _cononicalize_reloc */
+ _bfd_xcoff_reloc_type_lookup, /* _bfd_reloc_type_lookup */
+
+ /* Write */
+ coff_set_arch_mach, /* _set_arch_mach */
+ coff_set_section_contents, /* _set_section_contents */
+
+ /* Link */
+ _bfd_xcoff_sizeof_headers, /* _sizeof_headers */
+ /* _bfd_get_relocated_section_contents */
+ bfd_generic_get_relocated_section_contents,
+ bfd_generic_relax_section, /* _bfd_relax_section */
+ _bfd_xcoff_bfd_link_hash_table_create, /* _bfd_link_hash_table_create */
+ _bfd_xcoff_bfd_link_add_symbols, /* _bfd_link_add_symbols */
+ _bfd_xcoff_bfd_final_link, /* _bfd_filnal_link */
+ _bfd_generic_link_split_section, /* _bfd_link_split_section */
+ bfd_generic_gc_sections, /* _bfd_gc_sections */
+ bfd_generic_merge_sections, /* _bfd_merge_sections */
+
+ /* Dynamic */
+ /* _get_dynamic_symtab_upper_bound */
+ _bfd_xcoff_get_dynamic_symtab_upper_bound,
+ _bfd_xcoff_canonicalize_dynamic_symtab, /* _cononicalize_dynamic_symtab */
+ _bfd_xcoff_get_dynamic_reloc_upper_bound,/* _get_dynamic_reloc_upper_bound */
+ _bfd_xcoff_canonicalize_dynamic_reloc, /* _cononicalize_dynamic_reloc */
+
+ /* Opposite endian version, none exists */
+ NULL,
+
+ /* back end data */
+ (void *) &bfd_pmac_xcoff_backend_data,
+};
+
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index c07c41b509e..1968e0022f4 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -20,16 +20,15 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* Internalcoff.h and coffcode.h modify themselves based on these flags. */
-#define XCOFF64
-#define RS6000COFF_C 1
-
#include "bfd.h"
#include "sysdep.h"
+#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
+#include "coff/xcoff.h"
#include "coff/rs6k64.h"
-#include "libcoff.h"
+#include "libcoff.h"
+#include "libxcoff.h"
#define GET_FILEHDR_SYMPTR bfd_h_get_64
#define PUT_FILEHDR_SYMPTR bfd_h_put_64
@@ -69,15 +68,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define COFF_FORCE_SYMBOLS_IN_STRINGS
#define COFF_DEBUG_STRING_WIDE_PREFIX
+
#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD,INT,EXT) \
do { \
memset (((SCNHDR *)EXT)->s_pad, 0, sizeof (((SCNHDR *)EXT)->s_pad));\
-} while (0)
+} while(0)
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
#define NO_COFF_LINENOS
-#define coff_SWAP_lineno_in xcoff64_swap_lineno_in
-#define coff_SWAP_lineno_out xcoff64_swap_lineno_out
+#define coff_SWAP_lineno_in _bfd_xcoff64_swap_lineno_in
+#define coff_SWAP_lineno_out _bfd_xcoff64_swap_lineno_out
#define PUTWORD bfd_h_put_32
#define PUTHALF bfd_h_put_16
@@ -86,10 +91,11 @@ do { \
#define GETHALF bfd_h_get_16
#define GETBYTE bfd_h_get_8
-/* For XCOFF64, the effective width of symndx changes depending on
+
+/* For XCOFF64, the effective width of symndx changes depending on
whether we are the first entry. Sigh. */
static void
-xcoff64_swap_lineno_in (abfd, ext1, in1)
+_bfd_xcoff64_swap_lineno_in (abfd, ext1, in1)
bfd *abfd;
PTR ext1;
PTR in1;
@@ -99,15 +105,15 @@ xcoff64_swap_lineno_in (abfd, ext1, in1)
in->l_lnno = bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
if (in->l_lnno == 0)
- in->l_addr.l_symndx =
+ in->l_addr.l_symndx =
bfd_h_get_32(abfd, (bfd_byte *) ext->l_addr.l_symndx);
else
- in->l_addr.l_symndx =
- bfd_h_get_64(abfd, (bfd_byte *) ext->l_addr.l_symndx);
+ in->l_addr.l_paddr =
+ bfd_h_get_64(abfd, (bfd_byte *) ext->l_addr.l_paddr);
}
static unsigned int
-xcoff64_swap_lineno_out (abfd, inp, outp)
+_bfd_xcoff64_swap_lineno_out (abfd, inp, outp)
bfd *abfd;
PTR inp;
PTR outp;
@@ -121,27 +127,28 @@ xcoff64_swap_lineno_out (abfd, inp, outp)
if (in->l_lnno == 0)
bfd_h_put_32 (abfd, in->l_addr.l_symndx, (bfd_byte *)ext->l_addr.l_symndx);
else
- bfd_h_put_64 (abfd, in->l_addr.l_symndx, (bfd_byte *)ext->l_addr.l_symndx);
+ bfd_h_put_64 (abfd, in->l_addr.l_paddr, (bfd_byte *)ext->l_addr.l_paddr);
return bfd_coff_linesz (abfd);
}
-static void xcoff64_swap_sym_in PARAMS ((bfd *, PTR, PTR));
-static unsigned int xcoff64_swap_sym_out PARAMS ((bfd *, PTR, PTR));
-static void xcoff64_swap_aux_in PARAMS ((bfd *, PTR, int, int, int, int, PTR));
-static unsigned int xcoff64_swap_aux_out PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+
+static void _bfd_xcoff64_swap_sym_in PARAMS ((bfd *, PTR, PTR));
+static unsigned int _bfd_xcoff64_swap_sym_out PARAMS ((bfd *, PTR, PTR));
+static void _bfd_xcoff64_swap_aux_in PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+static unsigned int _bfd_xcoff64_swap_aux_out PARAMS ((bfd *, PTR, int, int, int, int, PTR));
static void
-xcoff64_swap_sym_in (abfd, ext1, in1)
+_bfd_xcoff64_swap_sym_in (abfd, ext1, in1)
bfd *abfd;
PTR ext1;
PTR in1;
{
- SYMENT *ext = (SYMENT *)ext1;
+ struct external_syment *ext = (struct external_syment *)ext1;
struct internal_syment *in = (struct internal_syment *)in1;
in->_n._n_n._n_zeroes = 0;
- in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
+ in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e_offset);
in->n_value = bfd_h_get_64(abfd, (bfd_byte *) ext->e_value);
in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
@@ -150,15 +157,15 @@ xcoff64_swap_sym_in (abfd, ext1, in1)
}
static unsigned int
-xcoff64_swap_sym_out (abfd, inp, extp)
+_bfd_xcoff64_swap_sym_out (abfd, inp, extp)
bfd *abfd;
PTR inp;
PTR extp;
{
struct internal_syment *in = (struct internal_syment *)inp;
- SYMENT *ext =(SYMENT *)extp;
+ struct external_syment *ext =(struct external_syment *)extp;
- bfd_h_put_32(abfd, in->_n._n_n._n_offset, (bfd_byte *) ext->e.e.e_offset);
+ bfd_h_put_32(abfd, in->_n._n_n._n_offset, (bfd_byte *) ext->e_offset);
bfd_h_put_64(abfd, in->n_value , (bfd_byte *) ext->e_value);
bfd_h_put_16(abfd, in->n_scnum , (bfd_byte *) ext->e_scnum);
bfd_h_put_16(abfd, in->n_type , (bfd_byte *) ext->e_type);
@@ -168,7 +175,7 @@ xcoff64_swap_sym_out (abfd, inp, extp)
}
static void
-xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
+_bfd_xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
bfd *abfd;
PTR ext1;
int type;
@@ -177,27 +184,18 @@ xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
int numaux;
PTR in1;
{
- AUXENT *ext = (AUXENT *)ext1;
+ union external_auxent *ext = (union external_auxent *)ext1;
union internal_auxent *in = (union internal_auxent *)in1;
switch (class) {
case C_FILE:
- if (ext->x_file.x_fname[0] == 0) {
+ if (ext->x_file.x_n.x_zeroes == 0) {
in->x_file.x_n.x_zeroes = 0;
- in->x_file.x_n.x_offset =
+ in->x_file.x_n.x_offset =
bfd_h_get_32(abfd, (bfd_byte *) ext->x_file.x_n.x_offset);
} else {
- if (numaux > 1)
- {
- if (indx == 0)
- memcpy (in->x_file.x_fname, ext->x_file.x_fname,
- numaux * sizeof (AUXENT));
- }
- else
- {
- memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
- }
- }
+ memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+ }
goto end;
/* RS/6000 "csect" auxents */
@@ -205,10 +203,14 @@ xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
case C_HIDEXT:
if (indx + 1 == numaux)
{
- in->x_csect.x_scnlen.l =
- bfd_h_get_32(abfd, ext->x_csect.x_scnlen_lo);
- /* FIXME: If we want section lengths larger than 32 bits, we need
- to modify the internal coff structures to support it. */
+ bfd_signed_vma h = 0;
+ bfd_vma l = 0;
+
+ h = bfd_h_get_signed_32(abfd, ext->x_csect.x_scnlen_hi);
+ l = bfd_h_get_32 (abfd, ext->x_csect.x_scnlen_lo);
+
+ in->x_csect.x_scnlen.l = h << 32 | (l & 0xffffffff);
+
in->x_csect.x_parmhash = bfd_h_get_32 (abfd,
ext->x_csect.x_parmhash);
in->x_csect.x_snhash = bfd_h_get_16 (abfd, ext->x_csect.x_snhash);
@@ -255,12 +257,14 @@ xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
end: ;
/* the semicolon is because MSVC doesn't like labels at
- end of block. */
+ end of block. */
}
+
+
static unsigned int
-xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
+_bfd_xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
bfd *abfd;
PTR inp;
int type;
@@ -270,24 +274,20 @@ xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
PTR extp;
{
union internal_auxent *in = (union internal_auxent *)inp;
- AUXENT *ext = (AUXENT *)extp;
+ union external_auxent *ext = (union external_auxent *)extp;
memset((PTR)ext, 0, bfd_coff_auxesz (abfd));
switch (class)
{
case C_FILE:
- if (in->x_file.x_fname[0] == 0)
- {
- PUTWORD(abfd, 0, (bfd_byte *) ext->x_file.x_n.x_zeroes);
- PUTWORD(abfd,
- in->x_file.x_n.x_offset,
+ if (ext->x_file.x_n.x_zeroes == 0) {
+ bfd_h_put_32 (abfd, 0, (bfd_byte *) ext->x_file.x_n.x_zeroes);
+ bfd_h_put_32 (abfd, in->x_file.x_n.x_offset,
(bfd_byte *) ext->x_file.x_n.x_offset);
- }
- else
- {
+ } else {
memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
- }
- PUTBYTE (abfd, _AUX_FILE, (bfd_byte *) ext->x_auxtype.x_auxtype);
+ }
+ bfd_h_put_8 (abfd, _AUX_FILE, (bfd_byte *) ext->x_auxtype.x_auxtype);
goto end;
/* RS/6000 "csect" auxents */
@@ -295,15 +295,20 @@ xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
case C_HIDEXT:
if (indx + 1 == numaux)
{
- PUTWORD (abfd, in->x_csect.x_scnlen.l, ext->x_csect.x_scnlen_lo);
- PUTWORD (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
- PUTHALF (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
+ bfd_vma temp;
+
+ temp = in->x_csect.x_scnlen.l & 0xffffffff;
+ bfd_h_put_32 (abfd, temp, ext->x_csect.x_scnlen_lo);
+ temp = in->x_csect.x_scnlen.l >> 32;
+ bfd_h_put_32 (abfd, temp, ext->x_csect.x_scnlen_hi);
+ bfd_h_put_32 (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
+ bfd_h_put_16 (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
/* We don't have to hack bitfields in x_smtyp because it's
defined by shifts-and-ands, which are equivalent on all
byte orders. */
- PUTBYTE (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
- PUTBYTE (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
- PUTBYTE (abfd, _AUX_CSECT, (bfd_byte *) ext->x_auxtype.x_auxtype);
+ bfd_h_put_8 (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
+ bfd_h_put_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
+ bfd_h_put_8 (abfd, _AUX_CSECT, (bfd_byte *) ext->x_auxtype.x_auxtype);
goto end;
}
break;
@@ -319,33 +324,1934 @@ xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
{
- bfd_h_put_64(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
- (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
- PUTBYTE (abfd, _AUX_FCN, (bfd_byte *) ext->x_auxtype.x_auxtype);
- PUTWORD(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
- (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx);
+ bfd_h_put_64(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
+ (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
+ bfd_h_put_8 (abfd, _AUX_FCN, (bfd_byte *) ext->x_auxtype.x_auxtype);
+ bfd_h_put_32(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
+ (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx);
}
if (ISFCN (type))
- PUTWORD (abfd, in->x_sym.x_misc.x_fsize,
- (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_fsize);
+ bfd_h_put_32 (abfd, in->x_sym.x_misc.x_fsize,
+ (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_fsize);
else
{
- bfd_h_put_32(abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
+ bfd_h_put_32(abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
(bfd_byte *)ext->x_sym.x_fcnary.x_lnsz.x_lnno);
- bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_size,
+ bfd_h_put_16(abfd, in->x_sym.x_misc.x_lnsz.x_size,
(bfd_byte *)ext->x_sym.x_fcnary.x_lnsz.x_size);
}
end:
+
return bfd_coff_auxesz (abfd);
}
-#define coff_SWAP_sym_in xcoff64_swap_sym_in
-#define coff_SWAP_sym_out xcoff64_swap_sym_out
-#define coff_SWAP_aux_in xcoff64_swap_aux_in
-#define coff_SWAP_aux_out xcoff64_swap_aux_out
+static boolean
+_bfd_xcoff64_put_symbol_name (bfd *abfd, struct bfd_strtab_hash *strtab,
+ struct internal_syment *sym,
+ const char *name) {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+
+ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+
+ indx = _bfd_stringtab_add (strtab, name, hash, false);
+
+ if (indx == (bfd_size_type) -1)
+ return false;
+
+ sym->_n._n_n._n_zeroes = 0;
+ sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+
+ return true;
+}
+
+static boolean
+_bfd_xcoff64_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct xcoff_loader_info *ldinfo;
+ struct internal_ldsym *ldsym;
+ const char *name;
+{
+
+ size_t len;
+ len = strlen (name);
+
+ if (ldinfo->string_size + len + 3 > ldinfo->string_alc){
+ size_t newalc;
+ bfd_byte *newstrings;
+
+ newalc = ldinfo->string_alc * 2;
+ if (newalc == 0)
+ newalc = 32;
+ while (ldinfo->string_size + len + 3 > newalc)
+ newalc *= 2;
+
+ newstrings = ((bfd_byte *)
+ bfd_realloc ((PTR) ldinfo->strings, newalc));
+ if (newstrings == NULL) {
+ ldinfo->failed = true;
+ return false;
+ }
+ ldinfo->string_alc = newalc;
+ ldinfo->strings = newstrings;
+ }
+
+ bfd_put_16 (ldinfo->output_bfd, len + 1,
+ ldinfo->strings + ldinfo->string_size);
+ strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
+ ldsym->_l._l_l._l_zeroes = 0;
+ ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
+ ldinfo->string_size += len + 3;
+
+ return true;
+}
+
+extern const bfd_target * rs6000coff_core_p ();
+extern boolean rs6000coff_core_file_matches_executable_p ();
+extern char *rs6000coff_core_file_failing_command PARAMS ((bfd *abfd));
+extern int rs6000coff_core_file_failing_signal PARAMS ((bfd *abfd));
+extern boolean _bfd_xcoff_mkobject PARAMS ((bfd *));
+extern boolean _bfd_xcoff_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+extern boolean _bfd_xcoff_is_local_label_name PARAMS ((bfd *, const char *));
+extern void xcoff64_rtype2howto
+ PARAMS ((arelent *, struct internal_reloc *));
+extern reloc_howto_type * xcoff64_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+extern boolean _bfd_xcoff_slurp_armap PARAMS ((bfd *));
+extern PTR _bfd_xcoff_read_ar_hdr PARAMS ((bfd *));
+extern bfd *_bfd_xcoff_openr_next_archived_file PARAMS ((bfd *, bfd *));
+extern int _bfd_xcoff_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+extern boolean _bfd_xcoff_write_armap
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+extern boolean _bfd_xcoff_write_archive_contents PARAMS ((bfd *));
+extern int _bfd_xcoff_sizeof_headers PARAMS ((bfd *, boolean));
+extern void _bfd_xcoff_swap_sym_in PARAMS ((bfd *, PTR, PTR));
+extern unsigned int _bfd_xcoff_swap_sym_out PARAMS ((bfd *, PTR, PTR));
+extern void _bfd_xcoff_swap_aux_in PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+extern unsigned int _bfd_xcoff_swap_aux_out PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+
+/* coffcode.h needs these to be defined */
+/* Internalcoff.h and coffcode.h modify themselves based on these flags. */
+#define XCOFF64
+#define RS6000COFF_C 1
+
+#define SELECT_RELOC(internal, howto) \
+ { \
+ internal.r_type = howto->type; \
+ internal.r_size = \
+ ((howto->complain_on_overflow == complain_overflow_signed \
+ ? 0x80 \
+ : 0) \
+ | (howto->bitsize - 1)); \
+ }
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+#define COFF_LONG_FILENAMES
+#define NO_COFF_SYMBOLS
+#define RTYPE2HOWTO(cache_ptr, dst) xcoff64_rtype2howto (cache_ptr, dst)
+#define coff_mkobject _bfd_xcoff_mkobject
+#define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
+#define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
+#define coff_bfd_reloc_type_lookup xcoff64_reloc_type_lookup
+#define CORE_FILE_P rs6000coff_core_p
+#define coff_SWAP_sym_in _bfd_xcoff64_swap_sym_in
+#define coff_SWAP_sym_out _bfd_xcoff64_swap_sym_out
+#define coff_SWAP_aux_in _bfd_xcoff64_swap_aux_in
+#define coff_SWAP_aux_out _bfd_xcoff64_swap_aux_out
+
+
+
+#include "coffcode.h"
+
+/* Routines to swap information in the XCOFF .loader section. If we
+ ever need to write an XCOFF loader, this stuff will need to be
+ moved to another file shared by the linker (which XCOFF calls the
+ ``binder'') and the loader. */
+
+/* Swap in the ldhdr structure. */
+
+static void
+xcoff64_swap_ldhdr_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldhdr *src;
+ struct internal_ldhdr *dst;
+ {
+ dst->l_version = bfd_get_32 (abfd, src->l_version);
+ dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
+ dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
+ dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
+ dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
+ dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
+ dst->l_impoff = bfd_get_64 (abfd, src->l_impoff);
+ dst->l_stoff = bfd_get_64 (abfd, src->l_stoff);
+ dst->l_symoff = bfd_get_64 (abfd, src->l_symoff);
+ dst->l_rldoff = bfd_get_64 (abfd, src->l_rldoff);
+}
+
+/* Swap out the ldhdr structure. */
+
+static void
+xcoff64_swap_ldhdr_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldhdr *src;
+ struct external_ldhdr *dst;
+{
+ bfd_put_32 (abfd, src->l_version, dst->l_version);
+ bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
+ bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
+ bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
+ bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
+ bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
+ bfd_put_64 (abfd, src->l_impoff, dst->l_impoff);
+ bfd_put_64 (abfd, src->l_stoff, dst->l_stoff);
+ bfd_put_64 (abfd, src->l_symoff, dst->l_symoff);
+ bfd_put_64 (abfd, src->l_rldoff, dst->l_rldoff);
+}
+
+/* Swap in the ldsym structure. */
+
+static void
+xcoff64_swap_ldsym_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldsym *src;
+ struct internal_ldsym *dst;
+{
+ /*
+ * XCOFF64 does not use l_zeroes like XCOFF32
+ * Set the internal l_zeroes to 0 so the common 32/64 code uses l_value
+ * as an offset into the loader symbol table
+ */
+ dst->_l._l_l._l_zeroes = 0;
+ dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->l_offset);
+ dst->l_value = bfd_get_64 (abfd, src->l_value);
+ dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
+ dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
+ dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
+ dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
+ dst->l_parm = bfd_get_32 (abfd, src->l_parm);
+}
+
+/* Swap out the ldsym structure. */
+
+static void
+xcoff64_swap_ldsym_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldsym *src;
+ struct external_ldsym *dst;
+{
+ bfd_put_64 (abfd, src->l_value, dst->l_value);
+ bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->l_offset);
+ bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
+ bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
+ bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
+ bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
+ bfd_put_32 (abfd, src->l_parm, dst->l_parm);
+}
+
+/* Swap in the ldrel structure. */
+
+static void
+xcoff64_swap_ldrel_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldrel *src;
+ struct internal_ldrel *dst;
+{
+ dst->l_vaddr = bfd_get_64 (abfd, src->l_vaddr);
+ dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
+ dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
+ dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
+}
+
+/* Swap out the ldrel structure. */
+
+static void
+xcoff64_swap_ldrel_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldrel *src;
+ struct external_ldrel *dst;
+{
+ bfd_put_64 (abfd, src->l_vaddr, dst->l_vaddr);
+ bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
+ bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
+ bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
+}
+
+static boolean
+xcoff64_write_object_contents (abfd)
+ bfd * abfd;
+{
+ asection *current;
+ boolean hasrelocs = false;
+ boolean haslinno = false;
+ file_ptr scn_base;
+ file_ptr reloc_base;
+ file_ptr lineno_base;
+ file_ptr sym_base;
+ unsigned long reloc_size = 0;
+ unsigned long lnno_size = 0;
+ boolean long_section_names;
+ asection *text_sec = ((void *)0) ;
+ asection *data_sec = ((void *)0) ;
+ asection *bss_sec = ((void *)0) ;
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+
+ bfd_set_error (bfd_error_system_call);
+
+ if (abfd->output_has_begun == false) {
+ if (! bfd_coff_compute_section_file_positions (abfd))
+ return false;
+ }
+
+ /* Work out the size of the reloc and linno areas */
+ reloc_base = obj_relocbase (abfd);
+
+ for (current = abfd->sections; current != NULL; current = current->next) {
+ reloc_size += current->reloc_count * bfd_coff_relsz (abfd);
+ }
+
+ lineno_base = reloc_base + reloc_size;
+
+ /* Make a pass through the symbol table to count line number entries and
+ put them into the correct asections */
+ lnno_size = coff_count_linenumbers (abfd) * bfd_coff_linesz (abfd);
+
+ sym_base = lineno_base + lnno_size;
+
+ /* Indicate in each section->line_filepos its actual file address */
+ for (current = abfd->sections; current != NULL; current = current->next) {
+ if (current->lineno_count) {
+ current->line_filepos = lineno_base;
+ current->moving_line_filepos = lineno_base;
+ lineno_base += current->lineno_count * bfd_coff_linesz (abfd);
+ } else {
+ current->line_filepos = 0;
+ }
+
+ if (current->reloc_count) {
+ current->rel_filepos = reloc_base;
+ reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
+ } else {
+ current->rel_filepos = 0;
+ }
+ }
+
+ if ((abfd->flags & EXEC_P) != 0) {
+ scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
+ internal_f.f_opthdr = bfd_coff_aoutsz (abfd);
+ } else {
+ scn_base = bfd_coff_filhsz (abfd);
+ internal_f.f_opthdr = 0;
+ }
+
+ internal_f.f_nscns = 0;
+
+ if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
+ return false;
+
+ long_section_names = false;
+ for (current = abfd->sections; current != NULL; current = current->next) {
+
+ struct internal_scnhdr section;
+ struct external_scnhdr buff;
+
+ internal_f.f_nscns++;
+
+ strncpy (section.s_name, current->name, SCNNMLEN);
+
+ section.s_vaddr = current->vma;
+ section.s_paddr = current->lma;
+ section.s_size = current->_raw_size;
+
+ /*
+ If this section has no size or is unloadable then the scnptr
+ will be 0 too
+ */
+ if (current->_raw_size == 0 ||
+ (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) {
+ section.s_scnptr = 0;
+ } else {
+ section.s_scnptr = current->filepos;
+ }
+
+ section.s_relptr = current->rel_filepos;
+ section.s_lnnoptr = current->line_filepos;
+ section.s_nreloc = current->reloc_count;
+
+ section.s_nlnno = current->lineno_count;
+ if (current->reloc_count != 0)
+ hasrelocs = true;
+ if (current->lineno_count != 0)
+ haslinno = true;
+
+ section.s_flags = sec_to_styp_flags (current->name, current->flags);
+
+ if (!strcmp (current->name, _TEXT)) {
+ text_sec = current;
+ } else if (!strcmp (current->name, _DATA)) {
+ data_sec = current;
+ } else if (!strcmp (current->name, _BSS)) {
+ bss_sec = current;
+ }
+
+ if (bfd_coff_swap_scnhdr_out (abfd, &section, &buff) == 0
+ || bfd_write ((PTR) (&buff), 1, bfd_coff_scnhsz (abfd), abfd)
+ != bfd_coff_scnhsz (abfd))
+ return false;
+ }
+
+ internal_f.f_timdat = 0;
+
+ internal_f.f_flags = 0;
+
+ if (!hasrelocs)
+ internal_f.f_flags |= F_RELFLG;
+ if (!haslinno)
+ internal_f.f_flags |= F_LNNO;
+ if (abfd->flags & EXEC_P)
+ internal_f.f_flags |= F_EXEC;
+
+ /* FIXME: this is wrong for PPC_PE! */
+ if (bfd_little_endian (abfd))
+ internal_f.f_flags |= F_AR32WR;
+ else
+ internal_f.f_flags |= F_AR32W;
+
+ if ((abfd->flags & DYNAMIC) != 0)
+ internal_f.f_flags |= F_SHROBJ;
+ if (bfd_get_section_by_name (abfd, _LOADER) != NULL)
+ internal_f.f_flags |= F_DYNLOAD;
+
+ memset (&internal_a, 0, sizeof internal_a);
+
+
+ /*
+ * This can only be called from the xcoff64 backend so the magic # must
+ * be for xcoff64
+ */
+ internal_f.f_magic = 0757;
+
+ internal_a.magic = (abfd->flags & D_PAGED) ? RS6K_AOUTHDR_ZMAGIC :
+ (abfd->flags & WP_TEXT) ? RS6K_AOUTHDR_NMAGIC :
+ RS6K_AOUTHDR_OMAGIC;
+
+ /* FIXME: Does anybody ever set this to another value? */
+ internal_a.vstamp = 0;
+
+ /* Now should write relocs, strings, syms */
+ obj_sym_filepos (abfd) = sym_base;
+
+ internal_f.f_symptr = 0;
+ internal_f.f_nsyms = 0;
+
+ /*
+ * If bfd_get_symcount (abfd) != 0, then we are not using the COFF
+ * backend linker, and obj_raw_syment_count is not valid until after
+ * coff_write_symbols is called.
+ */
+ if (bfd_get_symcount (abfd) != 0) {
+ int firstundef;
+
+ if (!coff_renumber_symbols (abfd, &firstundef))
+ return false;
+ coff_mangle_symbols (abfd);
+ if (! coff_write_symbols (abfd))
+ return false;
+ if (! coff_write_linenumbers (abfd))
+ return false;
+ if (! coff_write_relocs (abfd, firstundef))
+ return false;
+
+ internal_f.f_symptr = sym_base;
+ internal_f.f_nsyms = bfd_get_symcount (abfd);
+ } else if (obj_raw_syment_count (abfd) != 0) {
+ internal_f.f_symptr = sym_base;
+
+ /*
+ * AIX appears to require that F_RELFLG not be set if there are
+ * local symbols but no relocations.
+ */
+ internal_f.f_flags &=~ F_RELFLG;
+ } else {
+ internal_f.f_flags |= F_LSYMS;
+ }
+
+ if (text_sec) {
+ internal_a.tsize = bfd_get_section_size_before_reloc (text_sec);
+ internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
+ }
+
+ if (data_sec) {
+ internal_a.dsize = bfd_get_section_size_before_reloc (data_sec);
+ internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
+ }
+
+ if (bss_sec) {
+ internal_a.bsize = bfd_get_section_size_before_reloc (bss_sec);
+ if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
+ internal_a.data_start = bss_sec->vma;
+ }
+
+ internal_a.entry = bfd_get_start_address (abfd);
+ internal_f.f_nsyms = obj_raw_syment_count (abfd);
+
+ if (xcoff_data (abfd)->full_aouthdr) {
+
+ bfd_vma toc;
+ asection *loader_sec;
+
+ internal_a.vstamp = 1;
+
+ internal_a.o_snentry = xcoff_data (abfd)->snentry;
+ if (internal_a.o_snentry == 0)
+ internal_a.entry = (bfd_vma) -1;
+
+ if (text_sec != NULL) {
+ internal_a.o_sntext = text_sec->target_index;
+ internal_a.o_algntext = bfd_get_section_alignment (abfd, text_sec);
+ } else {
+ internal_a.o_sntext = 0;
+ internal_a.o_algntext = 0;
+ }
+
+ if (data_sec != NULL) {
+ internal_a.o_sndata = data_sec->target_index;
+ internal_a.o_algndata = bfd_get_section_alignment (abfd, data_sec);
+ } else {
+ internal_a.o_sndata = 0;
+ internal_a.o_algndata = 0;
+ }
+
+ loader_sec = bfd_get_section_by_name (abfd, ".loader");
+ if (loader_sec != NULL)
+ internal_a.o_snloader = loader_sec->target_index;
+ else
+ internal_a.o_snloader = 0;
+ if (bss_sec != NULL)
+ internal_a.o_snbss = bss_sec->target_index;
+ else
+ internal_a.o_snbss = 0;
+
+ toc = xcoff_data (abfd)->toc;
+ internal_a.o_toc = toc;
+ internal_a.o_sntoc = xcoff_data (abfd)->sntoc;
+
+ internal_a.o_modtype = xcoff_data (abfd)->modtype;
+ if (xcoff_data (abfd)->cputype != -1)
+ internal_a.o_cputype = xcoff_data (abfd)->cputype;
+ else
+ {
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_rs6000:
+ internal_a.o_cputype = 4;
+ break;
+ case bfd_arch_powerpc:
+ if (bfd_get_mach (abfd) == 0)
+ internal_a.o_cputype = 3;
+ else
+ internal_a.o_cputype = 1;
+ break;
+ default:
+ abort ();
+ }
+ }
+ internal_a.o_maxstack = xcoff_data (abfd)->maxstack;
+ internal_a.o_maxdata = xcoff_data (abfd)->maxdata;
+ }
+
+ if (bfd_seek (abfd, (file_ptr) 0, 0 ) != 0)
+ return false;
+
+ {
+ char * buff;
+ bfd_size_type amount;
+
+ buff = bfd_malloc (bfd_coff_filhsz (abfd));
+ if (buff == ((void *)0) )
+ return false;
+
+ bfd_coff_swap_filehdr_out (abfd, (PTR) & internal_f, (PTR) buff);
+ amount = bfd_write ((PTR) buff, 1, bfd_coff_filhsz (abfd), abfd);
+
+ free (buff);
+
+ if (amount != bfd_coff_filhsz (abfd))
+ return false;
+ }
+
+ if (abfd->flags & EXEC_P) {
+
+ char * buff;
+ bfd_size_type amount;
+
+ buff = bfd_malloc (bfd_coff_aoutsz (abfd));
+ if (buff == NULL)
+ return false;
+
+ bfd_coff_swap_aouthdr_out (abfd, (PTR) & internal_a, (PTR) buff);
+ amount = bfd_write ((PTR) buff, 1, bfd_coff_aoutsz (abfd), abfd);
+
+ free (buff);
+
+ if (amount != bfd_coff_aoutsz (abfd))
+ return false;
+ }
+
+
+ return true;
+}
+
+/* This is the relocation function for the RS/6000/POWER/PowerPC.
+ This is currently the only processor which uses XCOFF; I hope that
+ will never change. */
+
+boolean
+xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
+ input_section, contents, relocs, syms,
+ sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct xcoff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ struct reloc_howto_struct howto;
+ bfd_reloc_status_type rstat;
+
+ /* Relocation type R_REF is a special relocation type which is
+ merely used to prevent garbage collection from occurring for
+ the csect including the symbol which it references. */
+ if (rel->r_type == R_REF)
+ continue;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1) {
+ h = NULL;
+ sym = NULL;
+ addend = 0;
+ } else {
+ h = obj_xcoff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ addend = - sym->n_value;
+ }
+
+ /* We build the howto information on the fly. */
+
+ howto.type = rel->r_type;
+ howto.rightshift = 0;
+ howto.size = 4;
+ howto.bitsize = (rel->r_size & 0x3f) + 1;
+ howto.pc_relative = false;
+ howto.bitpos = 0;
+ if ((rel->r_size & 0x80) != 0)
+ howto.complain_on_overflow = complain_overflow_signed;
+ else
+ howto.complain_on_overflow = complain_overflow_bitfield;
+ howto.special_function = NULL;
+ howto.name = "internal";
+ howto.partial_inplace = true;
+
+ if (howto.bitsize == 64) {
+ howto.src_mask = howto.dst_mask = MINUS_ONE;
+ } else if (howto.bitsize == 32) {
+ howto.src_mask = howto.dst_mask = 0xffffffff;
+ } else {
+ howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
+ if (howto.bitsize == 16)
+ howto.size = 1;
+ }
+ howto.pcrel_offset = false;
+
+ val = 0;
+
+ if (h == NULL) {
+ asection *sec;
+
+ if (symndx == -1) {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ } else {
+ sec = sections[symndx];
+ /* Hack to make sure we use the right TOC anchor value
+ if this reloc is against the TOC anchor. */
+ if (sec->name[3] == '0'
+ && strcmp (sec->name, ".tc0") == 0)
+ val = xcoff_data (output_bfd)->toc;
+ else
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+
+ } else {
+
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak) {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+
+ } else if (h->root.type == bfd_link_hash_common) {
+ asection *sec;
+
+ sec = h->root.u.c.p->section;
+ val = (sec->output_section->vma
+ + sec->output_offset);
+ } else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
+ || (h->flags & XCOFF_IMPORT) != 0) {
+ /* Every symbol in a shared object is defined somewhere. */
+ val = 0;
+ } else if (! info->relocateable) {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma, true)))
+ return false;
+
+ /* Don't try to process the reloc. It can't help, and
+ it may generate another error. */
+ continue;
+ }
+ }
+
+ /* I took the relocation type definitions from two documents:
+ the PowerPC AIX Version 4 Application Binary Interface, First
+ Edition (April 1992), and the PowerOpen ABI, Big-Endian
+ 32-Bit Hardware Implementation (June 30, 1994). Differences
+ between the documents are noted below. */
+
+ switch (rel->r_type) {
+ case R_RTB:
+ case R_RRTBI:
+ case R_RRTBA:
+ /* These relocs are defined by the PowerPC ABI to be
+ relative branches which use half of the difference
+ between the symbol and the program counter. I can't
+ quite figure out when this is useful. These relocs are
+ not defined by the PowerOpen ABI. */
+ default:
+ (*_bfd_error_handler)
+ (_("%s: unsupported relocation type 0x%02x"),
+ bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ case R_POS:
+ /* Simple positive relocation. */
+ break;
+ case R_NEG:
+ /* Simple negative relocation. */
+ val = - val;
+ break;
+ case R_REL:
+ /* Simple PC relative relocation. */
+ howto.pc_relative = true;
+ break;
+ case R_TOC:
+ /* TOC relative relocation. The value in the instruction in
+ the input file is the offset from the input file TOC to
+ the desired location. We want the offset from the final
+ TOC to the desired location. We have:
+ isym = iTOC + in
+ iinsn = in + o
+ osym = oTOC + on
+ oinsn = on + o
+ so we must change insn by on - in.
+ */
+ case R_GL:
+ /* Global linkage relocation. The value of this relocation
+ is the address of the entry in the TOC section. */
+ case R_TCL:
+ /* Local object TOC address. I can't figure out the
+ difference between this and case R_GL. */
+ case R_TRL:
+ /* TOC relative relocation. A TOC relative load instruction
+ which may be changed to a load address instruction.
+ FIXME: We don't currently implement this optimization. */
+ case R_TRLA:
+ /* TOC relative relocation. This is a TOC relative load
+ address instruction which may be changed to a load
+ instruction. FIXME: I don't know if this is the correct
+ implementation. */
+ if (h != NULL && h->smclas != XMC_TD)
+ {
+ if (h->toc_section == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
+ bfd_get_filename (input_bfd), rel->r_vaddr,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ val = (h->toc_section->output_section->vma
+ + h->toc_section->output_offset);
+
+ }
+
+
+ val = ((val - xcoff_data (output_bfd)->toc)
+ - (sym->n_value - xcoff_data (input_bfd)->toc));
+
+ addend = 0;
+ break;
+ case R_BA:
+ /* Absolute branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CAI:
+ /* The PowerPC ABI defines this as an absolute call which
+ may be modified to become a relative call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBA:
+ /* Absolute branch which may be modified to become a
+ relative branch. */
+ case R_RBAC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to an absolute branch
+ to a symbol. The PowerOpen ABI does not define this
+ relocation type. */
+ case R_RBRC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to a relative branch.
+ The PowerOpen ABI does not define this relocation type. */
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ break;
+ case R_BR:
+ /* Relative branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CREL:
+ /* The PowerPC ABI defines this as a relative call which may
+ be modified to become an absolute call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBR:
+ /* A relative branch which may be modified to become an
+ absolute branch. FIXME: We don't implement this,
+ although we should for symbols of storage mapping class
+ XMC_XO. */
+ howto.pc_relative = true;
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ howto.size = 2;
+ howto.complain_on_overflow = complain_overflow_bitfield;
+ break;
+ case R_RL:
+ /* The PowerPC AIX ABI describes this as a load which may be
+ changed to a load address. The PowerOpen ABI says this
+ is the same as case R_POS. */
+ break;
+ case R_RLA:
+ /* The PowerPC AIX ABI describes this as a load address
+ which may be changed to a load. The PowerOpen ABI says
+ this is the same as R_POS. */
+ break;
+ }
+
+ /* If we see an R_BR or R_RBR reloc which is jumping to global
+ linkage code, and it is followed by an appropriate cror nop
+ instruction, we replace the cror with ld r2,40(r1). This
+ restores the TOC after the glink code. Contrariwise, if the
+ call is followed by a ld r2,40(r1), but the call is not
+ going to global linkage code, we can replace the load with a
+ cror. */
+ if ((rel->r_type == R_BR || rel->r_type == R_RBR) &&
+ h != NULL &&
+ h->root.type == bfd_link_hash_defined &&
+ (rel->r_vaddr - input_section->vma + 8
+ <= input_section->_cooked_size)) {
+
+ bfd_byte *pnext;
+ unsigned long next;
+
+ pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+ next = bfd_get_32 (input_bfd, pnext);
+
+
+ /* The _ptrgl function is magic. It is used by the AIX
+ * compiler to call a function through a pointer.
+ *
+ * special case XMC_GL, global linkage
+ */
+ if (h->smclas == XMC_GL
+ || strcmp (h->root.root.string, "._ptrgl") == 0)
+ {
+ if (next == 0x4def7b82 /* cror 15,15,15 */
+ || next == 0x4ffffb82 /* cror 31,31,31 */
+ || next == 0x60000000) /* ori r0,r0,0 */
+ bfd_put_32 (input_bfd, 0xe8410028, pnext); /* ld r2,40(r1) */
+ }
+ else
+ {
+ if (next == 0xe8410028) /* ld r2,40(r1) */
+ bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
+ }
+ }
+
+ /* A PC relative reloc includes the section address. */
+ if (howto.pc_relative)
+ addend += input_section->vma;
+
+ rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ char howto_name[10];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+ sprintf (howto_name, "0x%02x", rel->r_type);
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto_name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+
+/* 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. */
+
+
+reloc_howto_type xcoff64_howto_table[] =
+{
+ /* Standard 64 bit relocation. */
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit relocation, but store negative value. */
+ HOWTO (1, /* type */
+ 0, /* rightshift */
+ -4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_NEG", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit PC relative relocation. */
+ HOWTO (2, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit TOC relative relocation. */
+ HOWTO (3, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* I don't really know what this is. */
+ HOWTO (4, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RTB", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* External TOC relative symbol. */
+ HOWTO (5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_GL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Local TOC relative symbol. */
+ HOWTO (6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TCL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (7),
+
+ /* Non modifiable absolute branch. */
+ HOWTO (8, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BA", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (9),
+
+ /* Non modifiable relative branch. */
+ HOWTO (0xa, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BR", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (0xb),
+
+ /* Indirect load. */
+ HOWTO (0xc, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Load address. */
+ HOWTO (0xd, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (0xe),
+
+ /* Non-relocating reference. */
+ HOWTO (0xf, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REF", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (0x10),
+ EMPTY_HOWTO (0x11),
+
+ /* TOC relative indirect load. */
+ HOWTO (0x12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TOC relative load address. */
+ HOWTO (0x13, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable relative branch. */
+ HOWTO (0x14, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBI", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable absolute branch. */
+ HOWTO (0x15, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBA", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call absolute indirect. */
+ HOWTO (0x16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_CAI", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call relative. */
+ HOWTO (0x17, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_CREL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x18, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x19, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBAC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch relative. */
+ HOWTO (0x1a, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBR", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x1b, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBRC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false) /* pcrel_offset */
+
+};
+
+void
+xcoff64_rtype2howto (relent, internal)
+ arelent *relent;
+ struct internal_reloc *internal;
+{
+ relent->howto = xcoff64_howto_table + internal->r_type;
+
+ /* Check for relocs we don't know of. */
+ if (internal->r_type
+ >= sizeof (xcoff64_howto_table) / sizeof (xcoff64_howto_table[0]))
+ abort ();
+ if (internal->r_type != relent->howto->type)
+ abort ();
+
+ /* The r_size field of an XCOFF reloc encodes the bitsize of the
+ relocation, as well as indicating whether it is signed or not.
+ Doublecheck that the relocation information gathered from the
+ type matches this information. The bitsize is not significant
+ for R_REF relocs. */
+ if (relent->howto->dst_mask != 0
+ && (relent->howto->bitsize
+ != ((unsigned int) internal->r_size & 0x3f) + 1))
+ abort ();
+#if 0
+ if ((internal->r_size & 0x80) != 0
+ ? (relent->howto->complain_on_overflow != complain_overflow_signed)
+ : (relent->howto->complain_on_overflow != complain_overflow_bitfield))
+ abort ();
+#endif
+}
+
+reloc_howto_type *
+xcoff64_reloc_type_lookup (abfd, code)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_PPC_B26:
+ return &xcoff64_howto_table[0xa];
+ case BFD_RELOC_PPC_BA26:
+ return &xcoff64_howto_table[8];
+ case BFD_RELOC_PPC_TOC16:
+ return &xcoff64_howto_table[3];
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ return &xcoff64_howto_table[0];
+ case BFD_RELOC_64:
+ return &xcoff64_howto_table[0x1c];
+ default:
+ return NULL;
+ }
+}
+
+
+
+/* Read in the armap of an XCOFF archive. */
+
+boolean
+xcoff64_slurp_armap (abfd)
+ bfd *abfd;
+{
+ file_ptr off;
+ size_t namlen;
+ bfd_size_type sz;
+ bfd_byte *contents, *cend;
+ bfd_vma c, i;
+ carsym *arsym;
+ bfd_byte *p;
+
+ /* This is for the new format. */
+ struct xcoff_ar_hdr_big hdr;
+
+ if (xcoff_ardata (abfd) == NULL) {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ off = strtol (xcoff_ardata_big (abfd)->symoff64, (char **) NULL, 10);
+ if (off == 0) {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ if (bfd_seek (abfd, off, SEEK_SET) != 0)
+ return false;
+
+ /* The symbol table starts with a normal archive header. */
+ if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR_BIG, 1, abfd) != SIZEOF_AR_HDR_BIG)
+ return false;
+
+ /* Skip the name (normally empty). */
+ namlen = strtol (hdr.namlen, (char **) NULL, 10);
+ if (bfd_seek (abfd, ((namlen + 1) & ~1) + SXCOFFARFMAG, SEEK_CUR) != 0)
+ return false;
+
+ /* XXX This actually has to be a call to strtoll (at least on 32-bit
+ machines) since the field width is 20 and there numbers with more
+ than 32 bits can be represented. */
+ sz = strtol (hdr.size, (char **) NULL, 10);
+
+ /* Read in the entire symbol table. */
+ contents = (bfd_byte *) bfd_alloc (abfd, sz);
+ if (contents == NULL)
+ return false;
+ if (bfd_read ((PTR) contents, 1, sz, abfd) != sz)
+ return false;
+
+ /* The symbol table starts with an eight byte count. */
+ c = bfd_h_get_64 (abfd, contents);
+
+ if (c * 8 >= sz) {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_ardata (abfd)->symdefs = ((carsym *)
+ bfd_alloc (abfd, c * sizeof (carsym)));
+ if (bfd_ardata (abfd)->symdefs == NULL)
+ return false;
+
+ /* After the count comes a list of eight byte file offsets. */
+ for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8;
+ i < c;
+ ++i, ++arsym, p += 8)
+ arsym->file_offset = bfd_h_get_64 (abfd, p);
+
+ /* After the file offsets come null terminated symbol names. */
+ cend = contents + sz;
+ for (i = 0, arsym = bfd_ardata (abfd)->symdefs;
+ i < c;
+ ++i, ++arsym, p += strlen ((char *) p) + 1)
+ {
+ if (p >= cend)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ arsym->name = (char *) p;
+ }
+
+ bfd_ardata (abfd)->symdef_count = c;
+ bfd_has_map (abfd) = true;
+
+ return true;
+}
+
+
+
+/* See if this is an NEW XCOFF archive. */
+
+const bfd_target *
+xcoff64_archive_p (abfd)
+ bfd *abfd;
+{
+ char magic[SXCOFFARMAG];
+ /* This is the new format. */
+ struct xcoff_ar_file_hdr_big hdr;
+
+ if (bfd_read ((PTR) magic, SXCOFFARMAG, 1, abfd) != SXCOFFARMAG) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (strncmp (magic, XCOFFARMAGBIG, SXCOFFARMAG) != 0) {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
+ involves a cast, we can't do it as the left operand of
+ assignment. */
+ abfd->tdata.aout_ar_data =
+ (struct artdata *) bfd_zalloc (abfd, sizeof (struct artdata));
+
+ if (bfd_ardata (abfd) == (struct artdata *) NULL)
+ return NULL;
+
+ bfd_ardata (abfd)->cache = NULL;
+ bfd_ardata (abfd)->archive_head = NULL;
+ bfd_ardata (abfd)->symdefs = NULL;
+ bfd_ardata (abfd)->extended_names = NULL;
+
+ /* Copy over the magic string. */
+ memcpy (hdr.magic, magic, SXCOFFARMAG);
+
+ /* Now read the rest of the file header. */
+ if (bfd_read ((PTR) &hdr.memoff, SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG, 1,
+ abfd) != SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* XXX This actually has to be a call to strtoll (at least on 32-bit
+ machines) since the field width is 20 and there numbers with more
+ than 32 bits can be represented. */
+ bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
+ (char **) NULL, 10);
+
+ bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, SIZEOF_AR_FILE_HDR_BIG);
+ if (bfd_ardata (abfd)->tdata == NULL)
+ return NULL;
+
+ memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG);
+
+ if (! xcoff64_slurp_armap (abfd)) {
+
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = (struct artdata *) NULL;
+ return NULL;
+ }
+
+ return abfd->xvec;
+}
+
+
+/* Open the next element in an XCOFF archive. */
+
+bfd *
+xcoff64_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *last_file;
+{
+ file_ptr filestart;
+
+ if ((xcoff_ardata (archive) == NULL) ||
+ (! xcoff_big_format_p (archive))) {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ if (last_file == NULL) {
+ filestart = bfd_ardata (archive)->first_file_filepos;
+ } else {
+ /* XXX These actually have to be a calls to strtoll (at least
+ on 32-bit machines) since the fields's width is 20 and
+ there numbers with more than 32 bits can be represented. */
+ filestart = strtol (arch_xhdr_big (last_file)->nextoff, (char **) NULL,
+ 10);
+ }
+ /* XXX These actually have to be calls to strtoll (at least on 32-bit
+ machines) since the fields's width is 20 and there numbers with more
+ than 32 bits can be represented. */
+ if (filestart == 0
+ || filestart == strtol (xcoff_ardata_big (archive)->memoff,
+ (char **) NULL, 10)
+ || filestart == strtol (xcoff_ardata_big (archive)->symoff,
+ (char **) NULL, 10)) {
+ bfd_set_error (bfd_error_no_more_archived_files);
+ return NULL;
+ }
+
+ return _bfd_get_elt_at_filepos (archive, filestart);
+}
+
+/* We can't use the usual coff_sizeof_headers routine, because AIX
+ always uses an a.out header. */
+
+/*ARGSUSED*/
+int
+xcoff64_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc ATTRIBUTE_UNUSED;
+{
+ int size;
+
+ size = bfd_coff_filhsz(abfd);
+
+ /*
+ * Don't think the small aout header can be used since some of the the
+ * old elements have been reordered past the end of the old coff
+ * small aout size
+ */
+
+ if (xcoff_data (abfd)->full_aouthdr)
+ size += bfd_coff_aoutsz(abfd);
+
+ size += abfd->section_count * bfd_coff_scnhsz(abfd);
+ return size;
+}
+
+
+
+static asection *
+xcoff64_create_csect_from_smclas (abfd, aux, symbol_name)
+ bfd *abfd;
+ union internal_auxent *aux;
+ const char *symbol_name;
+{
+ asection *return_value = NULL;
+
+ /*
+ * Changes from 32 :
+ * .sv == 8, is only for 32 bit programs
+ * .ti == 12 and .tb == 13 are now reserved
+ */
+ static const char *names[19] = {
+ ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
+ NULL, ".bs", ".ds", ".uc", NULL, NULL, NULL, ".tc0",
+ ".td", ".sv64", ".sv3264"
+ };
+
+ if ((19 >= aux->x_csect.x_smclas) &&
+ (NULL != names[aux->x_csect.x_smclas])) {
+
+ return_value = bfd_make_section_anyway
+ (abfd, names[aux->x_csect.x_smclas]);
+
+ } else {
+ (*_bfd_error_handler)
+ (_("%s: symbol `%s' has unrecognized smclas %d"),
+ bfd_get_filename (abfd), symbol_name, aux->x_csect.x_smclas);
+ bfd_set_error (bfd_error_bad_value);
+ }
+
+ return return_value;
+}
+
+boolean
+xcoff64_is_lineno_count_overflow (abfd, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_vma value ATTRIBUTE_UNUSED;
+{
+ return false;
+}
+
+boolean
+xcoff64_is_reloc_count_overflow (abfd, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_vma value ATTRIBUTE_UNUSED;
+{
+ return false;
+}
+
+bfd_vma
+xcoff64_loader_symbol_offset (abfd, ldhdr)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct internal_ldhdr *ldhdr;
+{
+ return (ldhdr->l_symoff);
+}
+
+bfd_vma
+xcoff64_loader_reloc_offset (abfd, ldhdr)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct internal_ldhdr *ldhdr;
+{
+ return (ldhdr->l_rldoff);
+}
+
+/* The typical dynamic reloc. */
+
+static reloc_howto_type xcoff64_dynamic_reloc =
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false); /* pcrel_offset */
+
+static unsigned long xcoff64_glink_code[10] =
+{
+ 0xe9820000, /* ld r12,0(r2) */
+ 0xf8410028, /* std r2,40(r1) */
+ 0xe80c0000, /* ld r0,0(r12) */
+ 0xe84c0008, /* ld r0,8(r12) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x4e800420, /* bctr */
+ 0x00000000, /* start of traceback table */
+ 0x000ca000, /* traceback table */
+ 0x00000000, /* traceback table */
+ 0x00000018, /* ??? */
+};
+
+static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
+{
+ { /* COFF backend, defined in libcoff.h */
+ _bfd_xcoff64_swap_aux_in, /* _bfd_coff_swap_aux_in */
+ _bfd_xcoff64_swap_sym_in, /* _bfd_coff_swap_sym_in */
+ _bfd_xcoff64_swap_lineno_in, /* _bfd_coff_swap_lineno_in */
+ _bfd_xcoff64_swap_aux_out, /* _bfd_swap_aux_out */
+ _bfd_xcoff64_swap_sym_out, /* _bfd_swap_sym_out */
+ _bfd_xcoff64_swap_lineno_out, /* _bfd_swap_lineno_out */
+ coff_swap_reloc_out, /* _bfd_swap_reloc_out */
+ coff_swap_filehdr_out, /* _bfd_swap_filehdr_out */
+ coff_swap_aouthdr_out, /* _bfd_swap_aouthdr_out */
+ coff_swap_scnhdr_out, /* _bfd_swap_scnhdr_out */
+ FILHSZ, /* _bfd_filhsz */
+ AOUTSZ, /* _bfd_aoutsz */
+ SCNHSZ, /* _bfd_scnhsz */
+ SYMESZ, /* _bfd_symesz */
+ AUXESZ, /* _bfd_auxesz */
+ RELSZ, /* _bfd_relsz */
+ LINESZ, /* _bfd_linesz */
+ FILNMLEN, /* _bfd_filnmlen */
+ true, /* _bfd_coff_long_filenames */
+ false, /* _bfd_coff_long_section_names */
+ (3), /* _bfd_coff_default_section_alignment_power */
+ true, /* _bfd_coff_force_symnames_in_strings */
+ 4, /* _bfd_coff_debug_string_prefix_length */
+ coff_swap_filehdr_in, /* _bfd_coff_swap_filehdr_in */
+ coff_swap_aouthdr_in, /* _bfd_swap_aouthdr_in */
+ coff_swap_scnhdr_in, /* _bfd_swap_scnhdr_in */
+ coff_swap_reloc_in, /* _bfd_reloc_in */
+ coff_bad_format_hook, /* _bfd_bad_format_hook */
+ coff_set_arch_mach_hook, /* _bfd_set_arch_mach_hook */
+ coff_mkobject_hook, /* _bfd_mkobject_hook */
+ styp_to_sec_flags, /* _bfd_syp_to_sec_flags */
+ coff_set_alignment_hook, /* _bfd_set_alignment_hook */
+ coff_slurp_symbol_table, /* _bfd_coff_slurp_symbol_table */
+ symname_in_debug_hook, /* _coff_symname_in_debug_hook */
+ coff_pointerize_aux_hook, /* _bfd_coff_pointerize_aux_hook */
+ coff_print_aux, /* bfd_coff_print_aux */
+ dummy_reloc16_extra_cases, /* _bfd_coff_reloc16_extra_cases */
+ dummy_reloc16_estimate, /* _bfd_coff_reloc16_estimate */
+ NULL, /* bfd_coff_sym_is_global */
+ /* _bfd_coff_compute_section_file_positions */
+ coff_compute_section_file_positions,
+ NULL , /* _bfd_coff_start_final_link */
+ xcoff64_ppc_relocate_section, /* _bfd_coff_relocate_section */
+ coff_rtype_to_howto, /* _bfd_coff_rtype_to_howto */
+ NULL , /* _bfd_coff_addust_symndx */
+ _bfd_generic_link_add_one_symbol, /* _bfd_coff_add_one_symbol */
+ coff_link_output_has_begun, /* _bfd_coff_link_output_has_begun */
+ coff_final_link_postscript /* _bfd_coff_final_link_postscript */
+ },
+
+ 0x01EF, /* magic number */
+ bfd_arch_powerpc, /* architecture */
+ bfd_mach_ppc_620, /* machine */
+
+ /* function pointers to xcoff specific swap routines */
+ xcoff64_swap_ldhdr_in, /* _xcoff_swap_ldhdr_in */
+ xcoff64_swap_ldhdr_out, /* _xcoff_swap_ldhdr_out */
+ xcoff64_swap_ldsym_in, /* _xcoff_swap_ldsym_in */
+ xcoff64_swap_ldsym_out, /* _xcoff_swap_ldsym_out */
+ xcoff64_swap_ldrel_in, /* _xcoff_swap_ldrel_in */
+ xcoff64_swap_ldrel_out, /* _xcoff_swap_ldrel_out */
+
+ /* sizes */
+ LDHDRSZ, /* _xcoff_ldhdrsz */
+ LDSYMSZ, /* _xcoff_ldsymsz */
+ LDRELSZ, /* _xcoff_ldrelsz */
+ 24, /* _xcoff_function_descriptor_size */
+ 0, /* _xcoff_small_aout_header_size */
+ /* versions */
+ 2, /* _xcoff_ldhdr_version */
+
+ /* xcoff vs xcoff64 putting symbol names */
+ _bfd_xcoff64_put_symbol_name, /* _xcoff_put_symbol_name */
+ _bfd_xcoff64_put_ldsymbol_name, /* _xcoff_put_ldsymbol_name */
+
+ /* dynamic reloc howto */
+ &xcoff64_dynamic_reloc,
+
+ xcoff64_create_csect_from_smclas,
+
+ /* lineno and reloc count overflow */
+ xcoff64_is_lineno_count_overflow,
+ xcoff64_is_reloc_count_overflow,
+
+ xcoff64_loader_symbol_offset,
+ xcoff64_loader_reloc_offset,
+
+ /* glink */
+ &xcoff64_glink_code[0],
+ 40, /* _xcoff_glink_size */
+
+};
+
+/* The transfer vector that leads the outside world to all of the above. */
+const bfd_target rs6000coff64_vec =
+{
+ "aixcoff64-rs6000",
+ bfd_target_xcoff_flavour,
+ 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 | DYNAMIC |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ /* data */
+ bfd_getb64, /* bfd_getx64 */
+ bfd_getb_signed_64, /* bfd_getx_signed_64 */
+ bfd_putb64, /* bfd_putx64 */
+ bfd_getb32, /* bfd_getx32 */
+ bfd_getb_signed_32, /* bfd_getx_signed_32 */
+ bfd_putb32, /* bfd_putx32 */
+ bfd_getb16, /* bfd_getx16 */
+ bfd_getb_signed_16, /* bfd_getx_signed_16 */
+ bfd_putb16, /* bfd_putx16 */
+
+ /* hdrs */
+ bfd_getb64, /* bfd_h_getx64 */
+ bfd_getb_signed_64, /* bfd_h_getx_signed_64 */
+ bfd_putb64, /* bfd_h_putx64 */
+ bfd_getb32, /* bfd_h_getx32 */
+ bfd_getb_signed_32, /* bfd_h_getx_signed_32 */
+ bfd_putb32, /* bfd_h_putx32 */
+ bfd_getb16, /* bfd_h_getx16 */
+ bfd_getb_signed_16, /* bfd_h_getx_signed_16 */
+ bfd_putb16, /* bfd_h_putx16 */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target,
+ coff_object_p,
+ xcoff64_archive_p,
+ rs6000coff_core_p
+ },
+
+ { /* bfd_set_format */
+ bfd_false,
+ coff_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ {/* bfd_write_contents */
+ bfd_false,
+ xcoff64_write_object_contents,
+ _bfd_xcoff_write_archive_contents,
+ bfd_false
+ },
+
+ /* Generic */
+ bfd_true, /* _close_and_cleanup */
+ bfd_true, /* _bfd_free_cached_info */
+ coff_new_section_hook, /* _new_section_hook */
+ _bfd_generic_get_section_contents, /* _bfd_get_section_contents */
+ /* _bfd_get_section_contents_in_window */
+ _bfd_generic_get_section_contents_in_window,
+
+ /* Copy */
+ _bfd_xcoff_copy_private_bfd_data, /* _bfd_copy_private_bfd */
+ /* _bfd_merge_private_bfd_data */
+ ((boolean (*) (bfd *, bfd *)) bfd_true),
+ /* _bfd_copy_pivate_section_data */
+ ((boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
+ /* _bfd_copy_private_symbol_data */
+ ((boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
+ ((boolean (*) (bfd *, flagword)) bfd_true), /* _bfd_set_private_flags */
+ ((boolean (*) (bfd *, void * )) bfd_true), /* _bfd_print_private_bfd_data */
+
+ /* Core */
+ rs6000coff_core_file_failing_command, /* _core_file_failing_command */
+ rs6000coff_core_file_failing_signal, /* _core_file_failing_signal */
+ /* _core_file_matches_executable_p */
+ rs6000coff_core_file_matches_executable_p,
+
+ /* Archive */
+ xcoff64_slurp_armap, /* _slurp_armap */
+ /* XCOFF archives do not have
+ anything which corresponds to
+ an extended name table. */
+ bfd_false, /* _slurp_extended_name_table */
+ /* _construct_extended_name_table */
+ ((boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
+ bfd_dont_truncate_arname, /* _truncate_arname */
+ _bfd_xcoff_write_armap, /* _write_armap */
+ _bfd_xcoff_read_ar_hdr, /* _read_ar_hdr */
+ xcoff64_openr_next_archived_file, /* _openr_next_archived_file */
+ _bfd_generic_get_elt_at_index, /* _get_elt_at_index */
+ _bfd_xcoff_generic_stat_arch_elt, /* _generic_dtat_arch_elt */
+ /* XCOFF archives do not have
+ a timestamp. */
+ bfd_true, /* _update_armap_timestamp */
+
+ /* Symbols */
+ coff_get_symtab_upper_bound, /* _get_symtab_upper_bound */
+ coff_get_symtab, /* _get_symtab */
+ coff_make_empty_symbol, /* _make_empty_symbol */
+ coff_print_symbol, /* _print_symbol */
+ coff_get_symbol_info, /* _get_symbol_info */
+ _bfd_xcoff_is_local_label_name, /* _bfd_is_local_label_name */
+ coff_get_lineno, /* _get_lineno */
+ coff_find_nearest_line, /* _find_nearest_line */
+ coff_bfd_make_debug_symbol, /* _bfd_make_debug_symbol */
+ _bfd_generic_read_minisymbols, /* _read_minisymbols */
+ _bfd_generic_minisymbol_to_symbol, /* _minsymbol_to_symbol */
+
+ /* Reloc */
+ coff_get_reloc_upper_bound, /* _get_reloc_upper_bound */
+ coff_canonicalize_reloc, /* _cononicalize_reloc */
+ xcoff64_reloc_type_lookup, /* _bfd_reloc_type_lookup */
+
+ /* Write */
+ coff_set_arch_mach, /* _set_arch_mach */
+ coff_set_section_contents, /* _set_section_contents */
+
+ /* Link */
+ xcoff64_sizeof_headers, /* _sizeof_headers */
+ /* _bfd_get_relocated_section_contents */
+ bfd_generic_get_relocated_section_contents,
+ bfd_generic_relax_section, /* _bfd_relax_section */
+ _bfd_xcoff_bfd_link_hash_table_create, /* _bfd_link_hash_table_create */
+ _bfd_xcoff_bfd_link_add_symbols, /* _bfd_link_add_symbols */
+ _bfd_xcoff_bfd_final_link, /* _bfd_filnal_link */
+ _bfd_generic_link_split_section, /* _bfd_link_split_section */
+ bfd_generic_gc_sections, /* _bfd_gc_sections */
+ bfd_generic_merge_sections, /* _bfd_merge_sections */
+
+ /* Dynamic */
+ /* _get_dynamic_symtab_upper_bound */
+ _bfd_xcoff_get_dynamic_symtab_upper_bound,
+ _bfd_xcoff_canonicalize_dynamic_symtab, /* _cononicalize_dynamic_symtab */
+ _bfd_xcoff_get_dynamic_reloc_upper_bound,/* _get_dynamic_reloc_upper_bound */
+ _bfd_xcoff_canonicalize_dynamic_reloc, /* _cononicalize_dynamic_reloc */
+
+ /* Opposite endian version, none exists */
+ NULL,
+
+ /* back end data */
+ (void *) &bfd_xcoff_backend_data,
+};
-#define TARGET_NAME "aixcoff64-rs6000"
-#define TARGET_SYM rs6000coff64_vec
-#include "xcoff-target.h"
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 7415b964af0..6aafa50d26b 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -2053,21 +2053,8 @@ coff_set_arch_mach_hook (abfd, filehdr)
{
default:
case 0:
-#ifdef POWERMAC
- /* PowerPC Macs use the same magic numbers as RS/6000
- (because that's how they were bootstrapped originally),
- but they are always PowerPC architecture. */
- arch = bfd_arch_powerpc;
- machine = bfd_mach_ppc;
-#else
-#ifdef XCOFF64
- arch = bfd_arch_powerpc;
- machine = bfd_mach_ppc_620;
-#else
- arch = bfd_arch_rs6000;
- machine = bfd_mach_rs6k;
-#endif
-#endif /* POWERMAC */
+ arch = bfd_xcoff_architecture (abfd);
+ machine = bfd_xcoff_machine (abfd);
break;
case 1:
@@ -2338,13 +2325,21 @@ coff_print_aux (abfd, file, table_base, symbol, aux, indaux)
if (SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp) != XTY_LD)
{
BFD_ASSERT (! aux->fix_scnlen);
- fprintf (file, "val %5ld", aux->u.auxent.x_csect.x_scnlen.l);
+#ifdef XCOFF64
+ fprintf (file, "val %5lld", aux->u.auxent.x_csect.x_scnlen.l);
+#else
+ fprintf (file, "val %5ld", (long) aux->u.auxent.x_csect.x_scnlen.l);
+#endif
}
else
{
fprintf (file, "indx ");
if (! aux->fix_scnlen)
- fprintf (file, "%4ld", aux->u.auxent.x_csect.x_scnlen.l);
+#ifdef XCOFF64
+ fprintf (file, "%4lld", aux->u.auxent.x_csect.x_scnlen.l);
+#else
+ fprintf (file, "%4ld", (long) aux->u.auxent.x_csect.x_scnlen.l);
+#endif
else
fprintf (file, "%4ld",
(long) (aux->u.auxent.x_csect.x_scnlen.p - table_base));
@@ -3370,10 +3365,12 @@ coff_write_object_contents (abfd)
{
scn_base = bfd_coff_filhsz (abfd);
#ifdef RS6000COFF_C
+#ifndef XCOFF64
if (xcoff_data (abfd)->full_aouthdr)
scn_base += bfd_coff_aoutsz (abfd);
else
scn_base += SMALL_AOUTSZ;
+#endif
#endif
}
@@ -3625,6 +3622,7 @@ coff_write_object_contents (abfd)
}
#ifdef RS6000COFF_C
+#ifndef XCOFF64
/* XCOFF handles overflows in the reloc and line number count fields
by creating a new section header to hold the correct values. */
for (current = abfd->sections; current != NULL; current = current->next)
@@ -3652,6 +3650,7 @@ coff_write_object_contents (abfd)
}
}
#endif
+#endif
/* OK, now set up the filehdr... */
@@ -3673,10 +3672,12 @@ coff_write_object_contents (abfd)
{
internal_f.f_opthdr = 0;
#ifdef RS6000COFF_C
+#ifndef XCOFF64
if (xcoff_data (abfd)->full_aouthdr)
internal_f.f_opthdr = bfd_coff_aoutsz (abfd);
else
internal_f.f_opthdr = SMALL_AOUTSZ;
+#endif
#endif
}
@@ -4239,13 +4240,13 @@ coff_slurp_line_table (abfd, asect)
if (cache_ptr->line_number == 0)
{
boolean warned;
- long symndx;
+ bfd_signed_vma symndx;
coff_symbol_type *sym;
warned = false;
symndx = dst.l_addr.l_symndx;
if (symndx < 0
- || (unsigned long) symndx >= obj_raw_syment_count (abfd))
+ || (bfd_vma) symndx >= obj_raw_syment_count (abfd))
{
(*_bfd_error_handler)
(_("%s: warning: illegal symbol index %ld in line numbers"),
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 82bfdc82c12..5ca9c982fc2 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -47,13 +47,13 @@ static void coff_fix_symbol_name
PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_size_type *,
asection **, bfd_size_type *));
static boolean coff_write_symbol
- PARAMS ((bfd *, asymbol *, combined_entry_type *, unsigned int *,
+ PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_vma *,
bfd_size_type *, asection **, bfd_size_type *));
static boolean coff_write_alien_symbol
- PARAMS ((bfd *, asymbol *, unsigned int *, bfd_size_type *,
+ PARAMS ((bfd *, asymbol *, bfd_vma *, bfd_size_type *,
asection **, bfd_size_type *));
static boolean coff_write_native_symbol
- PARAMS ((bfd *, coff_symbol_type *, unsigned int *, bfd_size_type *,
+ PARAMS ((bfd *, coff_symbol_type *, bfd_vma *, bfd_size_type *,
asection **, bfd_size_type *));
static void coff_pointerize_aux
PARAMS ((bfd *, combined_entry_type *, combined_entry_type *,
@@ -749,8 +749,9 @@ coff_mangle_symbols (bfd_ptr)
if (s->fix_value)
{
/* FIXME: We should use a union here. */
- s->u.syment.n_value =
- ((combined_entry_type *) s->u.syment.n_value)->offset;
+ s->u.syment.n_value =
+ (bfd_vma)((combined_entry_type *)
+ ((unsigned long) s->u.syment.n_value))->offset;
s->fix_value = 0;
}
if (s->fix_line)
@@ -921,7 +922,7 @@ coff_write_symbol (abfd, symbol, native, written, string_size_p,
bfd *abfd;
asymbol *symbol;
combined_entry_type *native;
- unsigned int *written;
+ bfd_vma *written;
bfd_size_type *string_size_p;
asection **debug_string_section_p;
bfd_size_type *debug_string_size_p;
@@ -1006,7 +1007,7 @@ coff_write_alien_symbol (abfd, symbol, written, string_size_p,
debug_string_section_p, debug_string_size_p)
bfd *abfd;
asymbol *symbol;
- unsigned int *written;
+ bfd_vma *written;
bfd_size_type *string_size_p;
asection **debug_string_section_p;
bfd_size_type *debug_string_size_p;
@@ -1074,7 +1075,7 @@ coff_write_native_symbol (abfd, symbol, written, string_size_p,
debug_string_section_p, debug_string_size_p)
bfd *abfd;
coff_symbol_type *symbol;
- unsigned int *written;
+ bfd_vma *written;
bfd_size_type *string_size_p;
asection **debug_string_section_p;
bfd_size_type *debug_string_size_p;
@@ -1147,7 +1148,7 @@ coff_write_symbols (abfd)
bfd_size_type debug_string_size;
unsigned int i;
unsigned int limit = bfd_get_symcount (abfd);
- unsigned int written = 0;
+ bfd_signed_vma written = 0;
asymbol **p;
string_size = 0;
@@ -1917,11 +1918,8 @@ coff_get_symbol_info (abfd, symbol, ret)
if (coffsymbol (symbol)->native != NULL
&& coffsymbol (symbol)->native->fix_value)
{
- combined_entry_type *psym;
-
- psym = ((combined_entry_type *)
- coffsymbol (symbol)->native->u.syment.n_value);
- ret->value = (bfd_vma) (psym - obj_raw_syments (abfd));
+ ret->value = coffsymbol (symbol)->native->u.syment.n_value -
+ (unsigned long) obj_raw_syments (abfd);
}
}
@@ -1945,8 +1943,8 @@ bfd_coff_get_syment (abfd, symbol, psyment)
*psyment = csym->native->u.syment;
if (csym->native->fix_value)
- psyment->n_value = ((combined_entry_type *) psyment->n_value
- - obj_raw_syments (abfd));
+ psyment->n_value = psyment->n_value -
+ (unsigned long) obj_raw_syments (abfd);
/* FIXME: We should handle fix_line here. */
@@ -2023,7 +2021,7 @@ coff_print_symbol (abfd, filep, symbol, how)
case bfd_print_symbol_all:
if (coffsymbol (symbol)->native)
{
- unsigned long val;
+ bfd_vma val;
unsigned int aux;
combined_entry_type *combined = coffsymbol (symbol)->native;
combined_entry_type *root = obj_raw_syments (abfd);
@@ -2032,12 +2030,11 @@ coff_print_symbol (abfd, filep, symbol, how)
fprintf (file, "[%3ld]", (long) (combined - root));
if (! combined->fix_value)
- val = (unsigned long) combined->u.syment.n_value;
+ val = (bfd_vma) combined->u.syment.n_value;
else
- val = ((unsigned long)
- ((combined_entry_type *) combined->u.syment.n_value
- - root));
+ val = combined->u.syment.n_value - (unsigned long) root;
+#ifndef XCOFF64
fprintf (file,
"(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x%08lx %s",
combined->u.syment.n_scnum,
@@ -2045,8 +2042,20 @@ coff_print_symbol (abfd, filep, symbol, how)
combined->u.syment.n_type,
combined->u.syment.n_sclass,
combined->u.syment.n_numaux,
+ (unsigned long) val,
+ symbol->name);
+#else
+ /* Print out the wide, 64 bit, symbol value */
+ fprintf (file,
+ "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x%016llx %s",
+ combined->u.syment.n_scnum,
+ combined->u.syment.n_flags,
+ combined->u.syment.n_type,
+ combined->u.syment.n_sclass,
+ combined->u.syment.n_numaux,
val,
symbol->name);
+#endif
for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
{
diff --git a/bfd/coffswap.h b/bfd/coffswap.h
index 71e4462268a..2ff0a3231e6 100644
--- a/bfd/coffswap.h
+++ b/bfd/coffswap.h
@@ -286,6 +286,7 @@ coff_swap_filehdr_in (abfd, src, dst)
{
FILHDR *filehdr_src = (FILHDR *) src;
struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
+
#ifdef COFF_ADJUST_FILEHDR_IN_PRE
COFF_ADJUST_FILEHDR_IN_PRE (abfd, src, dst);
#endif
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 70fd06c6470..278381abb95 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -725,6 +725,10 @@ case "${targ}" in
targ_defvec=rs6000coff_vec
targ_selvecs="rs6000coff64_vec"
;;
+ powerpc64-*-aix*)
+ targ_defvec=rs6000coff64_vec
+ targ_selvecs="rs6000coff_vec"
+ ;;
powerpc-*-*bsd* | powerpc-*-elf* | powerpc-*-sysv4* | powerpc-*-eabi* | \
powerpc-*-solaris2* | powerpc-*-linux-gnu* | powerpc-*-rtems* | \
powerpc-*-chorus* | powerpc-*-vxworks*)
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 0df7e38e8b0..695df8d51ab 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -232,6 +232,7 @@ real_read (where, a,b, file)
if (a == 0 || b == 0)
return 0;
+
#if defined (__VAX) && defined (VMS)
/* Apparently fread on Vax VMS does not keep the record length
information. */
@@ -747,7 +748,6 @@ bfd_seek (abfd, position, direction)
file_position += abfd->origin;
result = fseek (f, file_position, direction);
-
if (result != 0)
{
int hold_errno = errno;
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 2a6d9ca84c7..8368cc85527 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -163,10 +163,10 @@ struct xcoff_tdata
short cputype;
/* maxdata from optional header. */
- bfd_size_type maxdata;
+ bfd_vma maxdata;
/* maxstack from optional header. */
- bfd_size_type maxstack;
+ bfd_vma maxstack;
/* Used by the XCOFF backend linker. */
asection **csects;
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 5127ff372e2..b7ed966f977 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -557,24 +557,6 @@ extern boolean _bfd_coff_reloc_link_order
#define coff_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
-/* Functions in xcofflink.c. */
-
-extern long _bfd_xcoff_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
-extern long _bfd_xcoff_canonicalize_dynamic_symtab
- PARAMS ((bfd *, asymbol **));
-extern long _bfd_xcoff_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
-extern long _bfd_xcoff_canonicalize_dynamic_reloc
- PARAMS ((bfd *, arelent **, asymbol **));
-extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
- PARAMS ((bfd *));
-extern boolean _bfd_xcoff_bfd_link_add_symbols
- PARAMS ((bfd *, struct bfd_link_info *));
-extern boolean _bfd_xcoff_bfd_final_link
- PARAMS ((bfd *, struct bfd_link_info *));
-extern boolean _bfd_ppc_xcoff_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- struct internal_reloc *, struct internal_syment *, asection **));
-
/* Functions in coff-ppc.c. FIXME: These are called be pe.em in the
linker, and so should start with bfd and be declared in bfd.h. */
diff --git a/bfd/libxcoff.h b/bfd/libxcoff.h
new file mode 100644
index 00000000000..a755665f040
--- /dev/null
+++ b/bfd/libxcoff.h
@@ -0,0 +1,266 @@
+/* BFD XCOFF object file private structure.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Tom Rix, Redhat.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef LIBXCOFF_H
+#define LIBXCOFF_H
+
+/* This is the backend information kept for XCOFF files. This
+ structure is constant for a particular backend. The first element
+ is the COFF backend data structure, so that XCOFF targets can use
+ the generic COFF code. */
+
+struct xcoff_backend_data_rec
+{
+ /*
+ * COFF backend information. Must be the first field.
+ * This is where the std coff swap table goes
+ */
+ bfd_coff_backend_data coff;
+
+ /* Magic number */
+ unsigned short _xcoff_magic_number;
+
+ /* Architecture and machine for coff_set_arch_mach_hook */
+ enum bfd_architecture _xcoff_architecture;
+ long _xcoff_machine;
+
+ /* function pointers to xcoff specific swap routines */
+ void (* _xcoff_swap_ldhdr_in)(bfd *, PTR, struct internal_ldhdr *);
+ void (* _xcoff_swap_ldhdr_out)(bfd *, struct internal_ldhdr *, PTR);
+ void (* _xcoff_swap_ldsym_in)(bfd *, PTR, struct internal_ldsym *);
+ void (* _xcoff_swap_ldsym_out)(bfd *, struct internal_ldsym *, PTR);
+ void (* _xcoff_swap_ldrel_in)(bfd *, PTR, struct internal_ldrel *);
+ void (* _xcoff_swap_ldrel_out)(bfd *, struct internal_ldrel *, PTR);
+
+ /* size of the the external struct */
+ unsigned int _xcoff_ldhdrsz;
+ unsigned int _xcoff_ldsymsz;
+ unsigned int _xcoff_ldrelsz;
+
+ /* size an entry in a descriptor section */
+ unsigned int _xcoff_function_descriptor_size;
+
+ /* size of the small aout file header */
+ unsigned int _xcoff_small_aout_header_size;
+
+ /*
+ * version
+ * loader version
+ * 1 : xcoff32
+ * 2 : xcoff64
+ */
+ unsigned long _xcoff_ldhdr_version;
+
+ boolean (* _xcoff_put_symbol_name)(bfd *, struct bfd_strtab_hash *,
+ struct internal_syment *,
+ const char *);
+
+ boolean (* _xcoff_put_ldsymbol_name)(bfd *, struct xcoff_loader_info *,
+ struct internal_ldsym *,
+ const char *);
+
+ reloc_howto_type *_xcoff_dynamic_reloc;
+
+ asection * (* _xcoff_create_csect_from_smclas) (bfd *, union internal_auxent *, const char *);
+
+ /*
+ * line_no and reloc overflow
+ * 32 overflows to another section when the line_no or reloc count go
+ * over 0xffff. 64 does not overflow.
+ */
+ boolean (*_xcoff_is_lineno_count_overflow)(bfd *, bfd_vma);
+ boolean (*_xcoff_is_reloc_count_overflow)(bfd *, bfd_vma);
+
+ /*
+ * .loader symbol table offset
+ * 32 is after the .loader header
+ * 64 is offset in .loader header
+ *
+ * Similar for the reloc table
+ */
+ bfd_vma (*_xcoff_loader_symbol_offset)(bfd *, struct internal_ldhdr *);
+ bfd_vma (*_xcoff_loader_reloc_offset)(bfd *, struct internal_ldhdr *);
+
+
+ /*
+ * Global linkage
+ *
+ * The first word of global linkage code must be be modified by
+ * filling in the correct TOC offset.
+ */
+ unsigned long *_xcoff_glink_code;
+
+ /*
+ * Size of the global link code in bytes of the xcoff_glink_code table
+ */
+ unsigned long _xcoff_glink_size;
+
+};
+
+/* Look up an entry in an XCOFF link hash table. */
+
+#define xcoff_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct xcoff_link_hash_entry *) \
+ bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse an XCOFF link hash table. */
+
+#define xcoff_link_hash_traverse(table, func, info) \
+ (bfd_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the XCOFF link hash table from the info structure. This is
+ just a cast. */
+
+#define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))
+
+
+#define xcoff_backend(abfd) \
+ ((struct xcoff_backend_data_rec *) (abfd)->xvec->backend_data)
+
+#define bfd_xcoff_magic_number(a) ((xcoff_backend(a)->_xcoff_magic_number))
+#define bfd_xcoff_architecture(a) ((xcoff_backend(a)->_xcoff_architecture))
+#define bfd_xcoff_machine(a) ((xcoff_backend(a)->_xcoff_machine))
+
+#define bfd_xcoff_swap_ldhdr_in(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldhdr_in) ((a), (b), (c)))
+
+#define bfd_xcoff_swap_ldhdr_out(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldhdr_out) ((a), (b), (c)))
+
+#define bfd_xcoff_swap_ldsym_in(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldsym_in) ((a), (b), (c)))
+
+#define bfd_xcoff_swap_ldsym_out(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldsym_out) ((a), (b), (c)))
+
+#define bfd_xcoff_swap_ldrel_in(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldrel_in) ((a), (b), (c)))
+
+#define bfd_xcoff_swap_ldrel_out(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_swap_ldrel_out) ((a), (b), (c)))
+
+#define bfd_xcoff_ldhdrsz(a) ((xcoff_backend(a)->_xcoff_ldhdrsz))
+#define bfd_xcoff_ldsymsz(a) ((xcoff_backend(a)->_xcoff_ldsymsz))
+#define bfd_xcoff_ldrelsz(a) ((xcoff_backend(a)->_xcoff_ldrelsz))
+#define bfd_xcoff_function_descriptor_size(a) \
+ ((xcoff_backend(a)->_xcoff_function_descriptor_size))
+#define bfd_xcoff_small_aout_header_size(a) \
+ ((xcoff_backend(a)->_xcoff_small_aout_header_size))
+
+#define bfd_xcoff_ldhdr_version(a) ((xcoff_backend(a)->_xcoff_ldhdr_version))
+
+#define bfd_xcoff_put_symbol_name(a, b, c, d) \
+ ((xcoff_backend(a)->_xcoff_put_symbol_name) ((a), (b), (c), (d)))
+
+#define bfd_xcoff_put_ldsymbol_name(a, b, c, d) \
+ ((xcoff_backend(a)->_xcoff_put_ldsymbol_name) ((a), (b), (c), (d)))
+
+/* Get the XCOFF hash table entries for a BFD. */
+#define obj_xcoff_sym_hashes(bfd) \
+ ((struct xcoff_link_hash_entry **) obj_coff_sym_hashes (bfd))
+
+#define bfd_xcoff_dynamic_reloc_howto(a) \
+ ((xcoff_backend(a)->_xcoff_dynamic_reloc))
+
+#define bfd_xcoff_create_csect_from_smclas(a, b, c) \
+ ((xcoff_backend(a)->_xcoff_create_csect_from_smclas((a), (b), (c))))
+
+#define bfd_xcoff_is_lineno_count_overflow(a, b) \
+ ((xcoff_backend(a)->_xcoff_is_lineno_count_overflow((a), (b))))
+
+#define bfd_xcoff_is_reloc_count_overflow(a, b) \
+ ((xcoff_backend(a)->_xcoff_is_reloc_count_overflow((a), (b))))
+
+#define bfd_xcoff_loader_symbol_offset(a, b) \
+ ((xcoff_backend(a)->_xcoff_loader_symbol_offset((a), (b))))
+
+#define bfd_xcoff_loader_reloc_offset(a, b) \
+ ((xcoff_backend(a)->_xcoff_loader_reloc_offset((a), (b))))
+
+#define bfd_xcoff_glink_code(a, b) ((xcoff_backend(a)->_xcoff_glink_code[(b)]))
+#define bfd_xcoff_glink_code_size(a) ((xcoff_backend(a)->_xcoff_glink_size))
+
+#define bfd_xcoff_is_xcoff64(a) (0x01EF == (bfd_xcoff_magic_number(a)))
+#define bfd_xcoff_is_xcoff32(a) (0x01DF == (bfd_xcoff_magic_number(a)))
+
+/* Functions in xcofflink.c. */
+
+extern long _bfd_xcoff_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
+extern long _bfd_xcoff_canonicalize_dynamic_symtab
+ PARAMS ((bfd *, asymbol **));
+extern long _bfd_xcoff_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
+extern long _bfd_xcoff_canonicalize_dynamic_reloc
+ PARAMS ((bfd *, arelent **, asymbol **));
+extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
+ PARAMS ((bfd *));
+extern boolean _bfd_xcoff_bfd_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_xcoff_bfd_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_xcoff_slurp_symbol_table
+ PARAMS ((bfd *));
+extern long _bfd_xcoff_get_symbol_table
+ PARAMS ((bfd *, asymbol **));
+extern asymbol *_bfd_xcoff_make_empty_symbol
+ PARAMS ((bfd *));
+extern long _bfd_xcoff_get_symbol_table_upper_bound
+ PARAMS ((bfd *));
+extern void _bfd_xcoff_print_symbol
+ PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
+extern void _bfd_xcoff_get_symbol_info
+ PARAMS ((bfd *, asymbol *, symbol_info *));
+extern long _bfd_xcoff_canonicalize_reloc
+ PARAMS((bfd *, sec_ptr, arelent **, asymbol **));
+extern reloc_howto_type *_bfd_xcoff_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+extern boolean _bfd_xcoff_set_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+boolean _bfd_xcoff_write_object_contents PARAMS ((bfd *));
+
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ boolean));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean xcoff_slurp_reloc_table
+ PARAMS ((bfd *, asection *, asymbol **));
+
+#endif /* LIBXCOFF_H */
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 5580e9b3543..4e25c595d45 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -24,186 +24,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
+#include "coff/xcoff.h"
#include "libcoff.h"
+#include "libxcoff.h"
/* This file holds the XCOFF linker code. */
#define STRING_SIZE_SIZE (4)
-/* Get the XCOFF hash table entries for a BFD. */
-#define obj_xcoff_sym_hashes(bfd) \
- ((struct xcoff_link_hash_entry **) obj_coff_sym_hashes (bfd))
-
-/* XCOFF relocation types. These probably belong in a header file
- somewhere. The relocations are described in the function
- _bfd_ppc_xcoff_relocate_section in this file. */
-
-#define R_POS (0x00)
-#define R_NEG (0x01)
-#define R_REL (0x02)
-#define R_TOC (0x03)
-#define R_RTB (0x04)
-#define R_GL (0x05)
-#define R_TCL (0x06)
-#define R_BA (0x08)
-#define R_BR (0x0a)
-#define R_RL (0x0c)
-#define R_RLA (0x0d)
-#define R_REF (0x0f)
-#define R_TRL (0x12)
-#define R_TRLA (0x13)
-#define R_RRTBI (0x14)
-#define R_RRTBA (0x15)
-#define R_CAI (0x16)
-#define R_CREL (0x17)
-#define R_RBA (0x18)
-#define R_RBAC (0x19)
-#define R_RBR (0x1a)
-#define R_RBRC (0x1b)
-
-/* The first word of global linkage code. This must be modified by
- filling in the correct TOC offset. */
-
-#define XCOFF_GLINK_FIRST (0x81820000) /* lwz r12,0(r2) */
-
-/* The remaining words of global linkage code. */
-
-static unsigned long xcoff_glink_code[] = {
- 0x90410014, /* stw r2,20(r1) */
- 0x800c0000, /* lwz r0,0(r12) */
- 0x804c0004, /* lwz r2,4(r12) */
- 0x7c0903a6, /* mtctr r0 */
- 0x4e800420, /* bctr */
- 0x0, /* start of traceback table */
- 0x000c8000, /* traceback table */
- 0x0 /* traceback table */
-};
-
-#define XCOFF_GLINK_SIZE \
- (((sizeof xcoff_glink_code / sizeof xcoff_glink_code[0]) * 4) + 4)
-
/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
This flag will only be used on input sections. */
#define SEC_MARK (SEC_ROM)
-/* The ldhdr structure. This appears at the start of the .loader
- section. */
-
-struct internal_ldhdr {
- /* The version number: currently always 1. */
- unsigned long l_version;
- /* The number of symbol table entries. */
- bfd_size_type l_nsyms;
- /* The number of relocation table entries. */
- bfd_size_type l_nreloc;
- /* The length of the import file string table. */
- bfd_size_type l_istlen;
- /* The number of import files. */
- bfd_size_type l_nimpid;
- /* The offset from the start of the .loader section to the first
- entry in the import file table. */
- bfd_size_type l_impoff;
- /* The length of the string table. */
- bfd_size_type l_stlen;
- /* The offset from the start of the .loader section to the first
- entry in the string table. */
- bfd_size_type l_stoff;
-};
-
-struct external_ldhdr {
- bfd_byte l_version[4];
- bfd_byte l_nsyms[4];
- bfd_byte l_nreloc[4];
- bfd_byte l_istlen[4];
- bfd_byte l_nimpid[4];
- bfd_byte l_impoff[4];
- bfd_byte l_stlen[4];
- bfd_byte l_stoff[4];
-};
-
-#define LDHDRSZ (8 * 4)
-
-/* The ldsym structure. This is used to represent a symbol in the
- .loader section. */
-
-struct internal_ldsym {
- union {
- /* The symbol name if <= SYMNMLEN characters. */
- char _l_name[SYMNMLEN];
- struct {
- /* Zero if the symbol name is more than SYMNMLEN characters. */
- long _l_zeroes;
- /* The offset in the string table if the symbol name is more
- than SYMNMLEN characters. */
- long _l_offset;
- } _l_l;
- } _l;
- /* The symbol value. */
- bfd_vma l_value;
- /* The symbol section number. */
- short l_scnum;
- /* The symbol type and flags. */
- char l_smtype;
- /* The symbol storage class. */
- char l_smclas;
- /* The import file ID. */
- bfd_size_type l_ifile;
- /* Offset to the parameter type check string. */
- bfd_size_type l_parm;
-};
-
-struct external_ldsym {
- union {
- bfd_byte _l_name[SYMNMLEN];
- struct {
- bfd_byte _l_zeroes[4];
- bfd_byte _l_offset[4];
- } _l_l;
- } _l;
- bfd_byte l_value[4];
- bfd_byte l_scnum[2];
- bfd_byte l_smtype[1];
- bfd_byte l_smclas[1];
- bfd_byte l_ifile[4];
- bfd_byte l_parm[4];
-};
-
-#define LDSYMSZ (8 + 3 * 4 + 2 + 2)
-
-/* These flags are for the l_smtype field (the lower three bits are an
- XTY_* value). */
-
-/* Imported symbol. */
-#define L_IMPORT (0x40)
-/* Entry point. */
-#define L_ENTRY (0x20)
-/* Exported symbol. */
-#define L_EXPORT (0x10)
-
-/* The ldrel structure. This is used to represent a reloc in the
- .loader section. */
-
-struct internal_ldrel {
- /* The reloc address. */
- bfd_vma l_vaddr;
- /* The symbol table index in the .loader section symbol table. */
- bfd_size_type l_symndx;
- /* The relocation type and size. */
- short l_rtype;
- /* The section number this relocation applies to. */
- short l_rsecnm;
-};
-
-struct external_ldrel {
- bfd_byte l_vaddr[4];
- bfd_byte l_symndx[4];
- bfd_byte l_rtype[2];
- bfd_byte l_rsecnm[2];
-};
-
-#define LDRELSZ (2 * 4 + 2 * 2)
-
/* The list of import files. */
struct xcoff_import_file {
@@ -217,134 +50,6 @@ struct xcoff_import_file {
const char *member;
};
-/* An entry in the XCOFF linker hash table. */
-
-struct xcoff_link_hash_entry {
- struct bfd_link_hash_entry root;
-
- /* Symbol index in output file. Set to -1 initially. Set to -2 if
- there is a reloc against this symbol. */
- long indx;
-
- /* If we have created a TOC entry for this symbol, this is the .tc
- section which holds it. */
- asection *toc_section;
-
- union {
- /* If we have created a TOC entry (the XCOFF_SET_TOC flag is set),
- this is the offset in toc_section. */
- bfd_vma toc_offset;
- /* If the TOC entry comes from an input file, this is set to the
- symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */
- long toc_indx;
- } u;
-
- /* If this symbol is a function entry point which is called, this
- field holds a pointer to the function descriptor. If this symbol
- is a function descriptor, this field holds a pointer to the
- function entry point. */
- struct xcoff_link_hash_entry *descriptor;
-
- /* The .loader symbol table entry, if there is one. */
- struct internal_ldsym *ldsym;
-
- /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table
- index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set,
- this is the l_ifile value. */
- long ldindx;
-
- /* Some linker flags. */
- unsigned short flags;
- /* Symbol is referenced by a regular object. */
-#define XCOFF_REF_REGULAR (01)
- /* Symbol is defined by a regular object. */
-#define XCOFF_DEF_REGULAR (02)
- /* Symbol is defined by a dynamic object. */
-#define XCOFF_DEF_DYNAMIC (04)
- /* Symbol is used in a reloc being copied into the .loader section. */
-#define XCOFF_LDREL (010)
- /* Symbol is the entry point. */
-#define XCOFF_ENTRY (020)
- /* Symbol is called; this is, it appears in a R_BR reloc. */
-#define XCOFF_CALLED (040)
- /* Symbol needs the TOC entry filled in. */
-#define XCOFF_SET_TOC (0100)
- /* Symbol is explicitly imported. */
-#define XCOFF_IMPORT (0200)
- /* Symbol is explicitly exported. */
-#define XCOFF_EXPORT (0400)
- /* Symbol has been processed by xcoff_build_ldsyms. */
-#define XCOFF_BUILT_LDSYM (01000)
- /* Symbol is mentioned by a section which was not garbage collected. */
-#define XCOFF_MARK (02000)
- /* Symbol size is recorded in size_list list from hash table. */
-#define XCOFF_HAS_SIZE (04000)
- /* Symbol is a function descriptor. */
-#define XCOFF_DESCRIPTOR (010000)
- /* Multiple definitions have been for the symbol. */
-#define XCOFF_MULTIPLY_DEFINED (020000)
-
- /* The storage mapping class. */
- unsigned char smclas;
-};
-
-/* The XCOFF linker hash table. */
-
-struct xcoff_link_hash_table {
- struct bfd_link_hash_table root;
-
- /* The .debug string hash table. We need to compute this while
- reading the input files, so that we know how large the .debug
- section will be before we assign section positions. */
- struct bfd_strtab_hash *debug_strtab;
-
- /* The .debug section we will use for the final output. */
- asection *debug_section;
-
- /* The .loader section we will use for the final output. */
- asection *loader_section;
-
- /* A count of non TOC relative relocs which will need to be
- allocated in the .loader section. */
- size_t ldrel_count;
-
- /* The .loader section header. */
- struct internal_ldhdr ldhdr;
-
- /* The .gl section we use to hold global linkage code. */
- asection *linkage_section;
-
- /* The .tc section we use to hold toc entries we build for global
- linkage code. */
- asection *toc_section;
-
- /* The .ds section we use to hold function descriptors which we
- create for exported symbols. */
- asection *descriptor_section;
-
- /* The list of import files. */
- struct xcoff_import_file *imports;
-
- /* Required alignment of sections within the output file. */
- unsigned long file_align;
-
- /* Whether the .text section must be read-only. */
- boolean textro;
-
- /* Whether garbage collection was done. */
- boolean gc;
-
- /* A linked list of symbols for which we have size information. */
- struct xcoff_link_size_list {
- struct xcoff_link_size_list *next;
- struct xcoff_link_hash_entry *h;
- bfd_size_type size;
- } *size_list;
-
- /* Magic sections: _text, _etext, _data, _edata, _end, end. */
- asection *special_sections[6];
-};
-
/* Information we keep for each section in the output file during the
final link phase. */
@@ -384,9 +89,9 @@ struct xcoff_final_link_info {
/* Symbol index of TOC symbol. */
long toc_symindx;
/* Start of .loader symbols. */
- struct external_ldsym *ldsym;
+ bfd_byte *ldsym;
/* Next .loader reloc to swap out. */
- struct external_ldrel *ldrel;
+ bfd_byte *ldrel;
/* File position of start of line numbers. */
file_ptr line_filepos;
/* Buffer large enough to hold swapped symbols of any input file. */
@@ -405,18 +110,6 @@ struct xcoff_final_link_info {
bfd_byte *external_relocs;
};
-static void xcoff_swap_ldhdr_in
- PARAMS ((bfd *, const struct external_ldhdr *, struct internal_ldhdr *));
-static void xcoff_swap_ldhdr_out
- PARAMS ((bfd *, const struct internal_ldhdr *, struct external_ldhdr *));
-static void xcoff_swap_ldsym_in
- PARAMS ((bfd *, const struct external_ldsym *, struct internal_ldsym *));
-static void xcoff_swap_ldsym_out
- PARAMS ((bfd *, const struct internal_ldsym *, struct external_ldsym *));
-static void xcoff_swap_ldrel_in
- PARAMS ((bfd *, const struct external_ldrel *, struct internal_ldrel *));
-static void xcoff_swap_ldrel_out
- PARAMS ((bfd *, const struct internal_ldrel *, struct external_ldrel *));
static struct bfd_hash_entry *xcoff_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static boolean xcoff_get_section_contents PARAMS ((bfd *, asection *));
@@ -451,121 +144,7 @@ static boolean xcoff_reloc_link_order
struct bfd_link_order *));
static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));
-/* Routines to swap information in the XCOFF .loader section. If we
- ever need to write an XCOFF loader, this stuff will need to be
- moved to another file shared by the linker (which XCOFF calls the
- ``binder'') and the loader. */
-
-/* Swap in the ldhdr structure. */
-
-static void
-xcoff_swap_ldhdr_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldhdr *src;
- struct internal_ldhdr *dst;
-{
- dst->l_version = bfd_get_32 (abfd, src->l_version);
- dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
- dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
- dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
- dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
- dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
- dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
- dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
-}
-
-/* Swap out the ldhdr structure. */
-
-static void
-xcoff_swap_ldhdr_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldhdr *src;
- struct external_ldhdr *dst;
-{
- bfd_put_32 (abfd, src->l_version, dst->l_version);
- bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
- bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
- bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
- bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
- bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
- bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
- bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
-}
-
-/* Swap in the ldsym structure. */
-
-static void
-xcoff_swap_ldsym_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldsym *src;
- struct internal_ldsym *dst;
-{
- if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0)
- memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
- else
- {
- dst->_l._l_l._l_zeroes = 0;
- dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
- }
- dst->l_value = bfd_get_32 (abfd, src->l_value);
- dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
- dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
- dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
- dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
- dst->l_parm = bfd_get_32 (abfd, src->l_parm);
-}
-/* Swap out the ldsym structure. */
-
-static void
-xcoff_swap_ldsym_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldsym *src;
- struct external_ldsym *dst;
-{
- if (src->_l._l_l._l_zeroes != 0)
- memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
- else
- {
- bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes);
- bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset);
- }
- bfd_put_32 (abfd, src->l_value, dst->l_value);
- bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
- bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
- bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
- bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
- bfd_put_32 (abfd, src->l_parm, dst->l_parm);
-}
-
-/* Swap in the ldrel structure. */
-
-static void
-xcoff_swap_ldrel_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldrel *src;
- struct internal_ldrel *dst;
-{
- dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
- dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
- dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
- dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
-}
-
-/* Swap out the ldrel structure. */
-
-static void
-xcoff_swap_ldrel_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldrel *src;
- struct external_ldrel *dst;
-{
- bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
- bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
- bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
- bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
-}
-
/* Routines to read XCOFF dynamic information. This don't really
belong here, but we already have the ldsym manipulation routines
here. */
@@ -577,6 +156,7 @@ xcoff_get_section_contents (abfd, sec)
bfd *abfd;
asection *sec;
{
+
if (coff_section_data (abfd, sec) == NULL)
{
sec->used_by_bfd = bfd_zalloc (abfd,
@@ -628,7 +208,7 @@ _bfd_xcoff_get_dynamic_symtab_upper_bound (abfd)
return -1;
contents = coff_section_data (abfd, lsec)->contents;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, (PTR) contents, &ldhdr);
return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
}
@@ -644,7 +224,7 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
- struct external_ldsym *elsym, *elsymend;
+ bfd_byte *elsym, *elsymend;
coff_symbol_type *symbuf;
if ((abfd->flags & DYNAMIC) == 0)
@@ -666,7 +246,7 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
coff_section_data (abfd, lsec)->keep_contents = true;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
strings = (char *) contents + ldhdr.l_stoff;
@@ -675,13 +255,14 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
if (symbuf == NULL)
return -1;
- elsym = (struct external_ldsym *) (contents + LDHDRSZ);
- elsymend = elsym + ldhdr.l_nsyms;
- for (; elsym < elsymend; elsym++, symbuf++, psyms++)
+ elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
+
+ elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
+ for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd), symbuf++, psyms++)
{
struct internal_ldsym ldsym;
- xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+ bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
symbuf->symbol.the_bfd = abfd;
@@ -689,24 +270,14 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
else
{
- int i;
-
- for (i = 0; i < SYMNMLEN; i++)
- if (ldsym._l._l_name[i] == '\0')
- break;
- if (i < SYMNMLEN)
- symbuf->symbol.name = (char *) elsym->_l._l_name;
- else
- {
- char *c;
-
- c = bfd_alloc (abfd, SYMNMLEN + 1);
- if (c == NULL)
- return -1;
- memcpy (c, ldsym._l._l_name, SYMNMLEN);
- c[SYMNMLEN] = '\0';
- symbuf->symbol.name = c;
- }
+ char *c;
+
+ c = bfd_alloc (abfd, SYMNMLEN + 1);
+ if (c == NULL)
+ return -1;
+ memcpy (c, ldsym._l._l_name, SYMNMLEN);
+ c[SYMNMLEN] = '\0';
+ symbuf->symbol.name = c;
}
if (ldsym.l_smclas == XMC_XO)
@@ -758,28 +329,11 @@ _bfd_xcoff_get_dynamic_reloc_upper_bound (abfd)
return -1;
contents = coff_section_data (abfd, lsec)->contents;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
}
-/* The typical dynamic reloc. */
-
-static reloc_howto_type xcoff_dynamic_reloc =
- HOWTO (0, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "R_POS", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false); /* pcrel_offset */
-
/* Get the dynamic relocs. */
long
@@ -792,7 +346,7 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
bfd_byte *contents;
struct internal_ldhdr ldhdr;
arelent *relbuf;
- struct external_ldrel *elrel, *elrelend;
+ bfd_byte *elrel, *elrelend;
if ((abfd->flags & DYNAMIC) == 0)
{
@@ -811,20 +365,21 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
return -1;
contents = coff_section_data (abfd, lsec)->contents;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent));
if (relbuf == NULL)
return -1;
- elrel = ((struct external_ldrel *)
- (contents + LDHDRSZ + ldhdr.l_nsyms * LDSYMSZ));
- elrelend = elrel + ldhdr.l_nreloc;
- for (; elrel < elrelend; elrel++, relbuf++, prelocs++)
+ elrel = contents + bfd_xcoff_loader_reloc_offset(abfd, &ldhdr);
+
+ elrelend = elrel + ldhdr.l_nreloc * bfd_xcoff_ldrelsz(abfd);
+ for (; elrel < elrelend; elrel += bfd_xcoff_ldrelsz(abfd), relbuf++,
+ prelocs++)
{
struct internal_ldrel ldrel;
- xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
+ bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
if (ldrel.l_symndx >= 3)
relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
@@ -865,7 +420,7 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
/* Most dynamic relocs have the same type. FIXME: This is only
correct if ldrel.l_rtype == 0. In other cases, we should use
a different howto. */
- relbuf->howto = &xcoff_dynamic_reloc;
+ relbuf->howto = bfd_xcoff_dynamic_reloc_howto(abfd);
/* FIXME: We have no way to record the l_rsecnm field. */
@@ -955,25 +510,6 @@ _bfd_xcoff_bfd_link_hash_table_create (abfd)
return &ret->root;
}
-/* Look up an entry in an XCOFF link hash table. */
-
-#define xcoff_link_hash_lookup(table, string, create, copy, follow) \
- ((struct xcoff_link_hash_entry *) \
- bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\
- (follow)))
-
-/* Traverse an XCOFF link hash table. */
-
-#define xcoff_link_hash_traverse(table, func, info) \
- (bfd_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
- (info)))
-
-/* Get the XCOFF link hash table from the info structure. This is
- just a cast. */
-
-#define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))
/* Read internal relocs for an XCOFF csect. This is a wrapper around
_bfd_coff_read_internal_relocs which tries to take advantage of any
@@ -989,6 +525,7 @@ xcoff_read_internal_relocs (abfd, sec, cache, external_relocs,
boolean require_internal;
struct internal_reloc *internal_relocs;
{
+
if (coff_section_data (abfd, sec) != NULL
&& coff_section_data (abfd, sec)->relocs == NULL
&& xcoff_section_data (abfd, sec) != NULL)
@@ -1018,6 +555,7 @@ xcoff_read_internal_relocs (abfd, sec, cache, external_relocs,
off = ((sec->rel_filepos - enclosing->rel_filepos)
/ bfd_coff_relsz (abfd));
+
if (! require_internal)
return coff_section_data (abfd, enclosing)->relocs + off;
memcpy (internal_relocs,
@@ -1039,6 +577,7 @@ _bfd_xcoff_bfd_link_add_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
+
switch (bfd_get_format (abfd))
{
case bfd_object:
@@ -1095,6 +634,7 @@ xcoff_link_add_object_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
+
if (! _bfd_coff_get_external_symbols (abfd))
return false;
if (! xcoff_link_add_symbols (abfd, info))
@@ -1118,6 +658,7 @@ xcoff_link_check_archive_element (abfd, info, pneeded)
struct bfd_link_info *info;
boolean *pneeded;
{
+
if (! _bfd_coff_get_external_symbols (abfd))
return false;
@@ -1178,6 +719,7 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
object file. */
name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+
if (name == NULL)
return false;
h = bfd_link_hash_lookup (info->hash, name, false, false, true);
@@ -1189,7 +731,7 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
undefined references in shared objects. */
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_undefined
- && (info->hash->creator != abfd->xvec
+ && (info->hash->creator != abfd->xvec
|| (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0))
{
@@ -1218,10 +760,10 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
boolean *pneeded;
{
asection *lsec;
- bfd_byte *buf;
+ bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
- struct external_ldsym *elsym, *elsymend;
+ bfd_byte *elsym, *elsymend;
*pneeded = false;
@@ -1234,22 +776,23 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
if (! xcoff_get_section_contents (abfd, lsec))
return false;
- buf = coff_section_data (abfd, lsec)->contents;
+ contents = coff_section_data (abfd, lsec)->contents;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
- strings = (char *) buf + ldhdr.l_stoff;
+ strings = (char *) contents + ldhdr.l_stoff;
+
+ elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
- elsym = (struct external_ldsym *) (buf + LDHDRSZ);
- elsymend = elsym + ldhdr.l_nsyms;
- for (; elsym < elsymend; elsym++)
+ elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
+ for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct bfd_link_hash_entry *h;
- xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+ bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
@@ -1283,7 +826,7 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
/* We do not need this shared object. */
- if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
+ if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
@@ -1342,6 +885,100 @@ xcoff_find_reloc (relocs, count, address)
return min;
}
+
+/*
+ * xcoff_link_create_extra_sections
+ *
+ * Takes care of creating the .loader, .gl, .ds, .debug and sections
+ */
+static boolean
+xcoff_link_create_extra_sections(bfd * abfd, struct bfd_link_info *info) {
+
+ boolean return_value = false;
+
+ if (info->hash->creator == abfd->xvec) {
+
+ /* We need to build a .loader section, so we do it here. This
+ won't work if we're producing an XCOFF output file with no
+ XCOFF input files. FIXME. */
+
+ if (xcoff_hash_table (info)->loader_section == NULL) {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".loader");
+ if (lsec == NULL) {
+ goto end_return;
+ }
+ xcoff_hash_table (info)->loader_section = lsec;
+ lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+
+ /* Likewise for the linkage section. */
+ if (xcoff_hash_table (info)->linkage_section == NULL) {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".gl");
+ if (lsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->linkage_section = lsec;
+ lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ lsec->alignment_power = 2;
+ }
+
+ /* Likewise for the TOC section. */
+ if (xcoff_hash_table (info)->toc_section == NULL) {
+ asection *tsec;
+
+ tsec = bfd_make_section_anyway (abfd, ".tc");
+ if (tsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->toc_section = tsec;
+ tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ tsec->alignment_power = 2;
+ }
+
+ /* Likewise for the descriptor section. */
+ if (xcoff_hash_table (info)->descriptor_section == NULL) {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".ds");
+ if (dsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->descriptor_section = dsec;
+ dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ dsec->alignment_power = 2;
+ }
+
+ /* Likewise for the .debug section. */
+ if (xcoff_hash_table (info)->debug_section == NULL
+ && info->strip != strip_all) {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".debug");
+ if (dsec == NULL) {
+ goto end_return;
+ }
+ xcoff_hash_table (info)->debug_section = dsec;
+ dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+ }
+
+ return_value = true;
+
+ end_return:
+
+ return return_value;
+}
+
/* Add all the symbols from an object file to the hash table.
XCOFF is a weird format. A normal XCOFF .o files will have three
@@ -1381,89 +1018,26 @@ xcoff_link_add_symbols (abfd, info)
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
- struct reloc_info_struct
- {
- struct internal_reloc *relocs;
- asection **csects;
- bfd_byte *linenos;
- } *reloc_info = NULL;
+ struct reloc_info_struct
+ {
+ struct internal_reloc *relocs;
+ asection **csects;
+ bfd_byte *linenos;
+ } *reloc_info = NULL;
keep_syms = obj_coff_keep_syms (abfd);
if ((abfd->flags & DYNAMIC) != 0
- && ! info->static_link)
- {
- if (! xcoff_link_add_dynamic_symbols (abfd, info))
- return false;
+ && ! info->static_link) {
+ if (! xcoff_link_add_dynamic_symbols (abfd, info)) {
+ return false;
}
+ }
- if (info->hash->creator == abfd->xvec)
- {
- /* We need to build a .loader section, so we do it here. This
- won't work if we're producing an XCOFF output file with no
- XCOFF input files. FIXME. */
- if (xcoff_hash_table (info)->loader_section == NULL)
- {
- asection *lsec;
-
- lsec = bfd_make_section_anyway (abfd, ".loader");
- if (lsec == NULL)
- goto error_return;
- xcoff_hash_table (info)->loader_section = lsec;
- lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
- }
- /* Likewise for the linkage section. */
- if (xcoff_hash_table (info)->linkage_section == NULL)
- {
- asection *lsec;
-
- lsec = bfd_make_section_anyway (abfd, ".gl");
- if (lsec == NULL)
- goto error_return;
- xcoff_hash_table (info)->linkage_section = lsec;
- lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY);
- lsec->alignment_power = 2;
- }
- /* Likewise for the TOC section. */
- if (xcoff_hash_table (info)->toc_section == NULL)
- {
- asection *tsec;
-
- tsec = bfd_make_section_anyway (abfd, ".tc");
- if (tsec == NULL)
- goto error_return;
- xcoff_hash_table (info)->toc_section = tsec;
- tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY);
- tsec->alignment_power = 2;
- }
- /* Likewise for the descriptor section. */
- if (xcoff_hash_table (info)->descriptor_section == NULL)
- {
- asection *dsec;
-
- dsec = bfd_make_section_anyway (abfd, ".ds");
- if (dsec == NULL)
- goto error_return;
- xcoff_hash_table (info)->descriptor_section = dsec;
- dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY);
- dsec->alignment_power = 2;
- }
- /* Likewise for the .debug section. */
- if (xcoff_hash_table (info)->debug_section == NULL
- && info->strip != strip_all)
- {
- asection *dsec;
-
- dsec = bfd_make_section_anyway (abfd, ".debug");
- if (dsec == NULL)
- goto error_return;
- xcoff_hash_table (info)->debug_section = dsec;
- dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
- }
- }
+ /* create the loader, toc, gl, ds and debug sections, if needed */
+ if (false == xcoff_link_create_extra_sections(abfd, info)) {
+ goto error_return;
+ }
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
@@ -1481,7 +1055,7 @@ xcoff_link_add_symbols (abfd, info)
else
default_copy = true;
- symcount = obj_raw_syment_count (abfd);
+ symcount = obj_raw_syment_count (abfd);
/* We keep a list of the linker hash table entries that correspond
to each external symbol. */
@@ -1521,37 +1095,40 @@ xcoff_link_add_symbols (abfd, info)
/* Read in the relocs and line numbers for each section. */
linesz = bfd_coff_linesz (abfd);
last_real = NULL;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- last_real = o;
- if ((o->flags & SEC_RELOC) != 0)
- {
- reloc_info[o->target_index].relocs =
- xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
- false, (struct internal_reloc *) NULL);
- reloc_info[o->target_index].csects =
- (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
- if (reloc_info[o->target_index].csects == NULL)
- goto error_return;
- memset (reloc_info[o->target_index].csects, 0,
- o->reloc_count * sizeof (asection *));
- }
+ for (o = abfd->sections; o != NULL; o = o->next) {
- if ((info->strip == strip_none || info->strip == strip_some)
- && o->lineno_count > 0)
- {
- bfd_byte *linenos;
+ last_real = o;
+ if ((o->flags & SEC_RELOC) != 0) {
- linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
- if (linenos == NULL)
- goto error_return;
- reloc_info[o->target_index].linenos = linenos;
- if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
- || (bfd_read (linenos, linesz, o->lineno_count, abfd)
- != linesz * o->lineno_count))
- goto error_return;
- }
+ reloc_info[o->target_index].relocs =
+ xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
+ false, (struct internal_reloc *) NULL);
+ reloc_info[o->target_index].csects =
+ (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
+ if (reloc_info[o->target_index].csects == NULL)
+ goto error_return;
+ memset (reloc_info[o->target_index].csects, 0,
+ o->reloc_count * sizeof (asection *));
+
+ }
+
+ if ((info->strip == strip_none || info->strip == strip_some)
+ && o->lineno_count > 0) {
+
+ bfd_byte *linenos;
+
+ linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
+ if (linenos == NULL)
+ goto error_return;
+ reloc_info[o->target_index].linenos = linenos;
+ if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
+ || (bfd_read (linenos, linesz, o->lineno_count, abfd)
+ != linesz * o->lineno_count))
+ goto error_return;
+
}
+ }
+
/* Don't let the linker relocation routines discard the symbols. */
obj_coff_keep_syms (abfd) = true;
@@ -1564,48 +1141,57 @@ xcoff_link_add_symbols (abfd, info)
BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
esym = (bfd_byte *) obj_coff_external_syms (abfd);
esym_end = esym + symcount * symesz;
- while (esym < esym_end)
- {
- struct internal_syment sym;
- union internal_auxent aux;
- const char *name;
- char buf[SYMNMLEN + 1];
- int smtyp;
- flagword flags;
- asection *section;
- bfd_vma value;
- struct xcoff_link_hash_entry *set_toc;
- bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+ while (esym < esym_end) {
+ struct internal_syment sym;
+ union internal_auxent aux;
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ int smtyp;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ struct xcoff_link_hash_entry *set_toc;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+
+ /* In this pass we are only interested in symbols with csect
+ information. */
+ if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT) {
+
+ /*
+ * Set csect_cache,
+ * Normally csect is a .pr, .rw etc. created in the loop
+ * If C_FILE or first time, handle special
+ *
+ * Advance esym, sym_hash, csect_hash ptr's
+ * Keep track of the last_symndx for the current file
+ */
+ if (sym.n_sclass == C_FILE && csect != NULL) {
+ xcoff_section_data (abfd, csect)->last_symndx =
+ ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+ csect = NULL;
+ }
- /* In this pass we are only interested in symbols with csect
- information. */
- if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
- {
- if (sym.n_sclass == C_FILE && csect != NULL)
- {
- xcoff_section_data (abfd, csect)->last_symndx =
- ((esym
- - (bfd_byte *) obj_coff_external_syms (abfd))
- / symesz);
- csect = NULL;
- }
+ if (csect != NULL)
+ *csect_cache = csect;
+ else if (first_csect == NULL || sym.n_sclass == C_FILE)
+ *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ else
+ *csect_cache = NULL;
+ esym += (sym.n_numaux + 1) * symesz;
+ sym_hash += sym.n_numaux + 1;
+ csect_cache += sym.n_numaux + 1;
+
+ continue;
+ }
- if (csect != NULL)
- *csect_cache = csect;
- else if (first_csect == NULL || sym.n_sclass == C_FILE)
- *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
- else
- *csect_cache = NULL;
- esym += (sym.n_numaux + 1) * symesz;
- sym_hash += sym.n_numaux + 1;
- csect_cache += sym.n_numaux + 1;
- continue;
- }
+ name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
- name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
- if (name == NULL)
- goto error_return;
+ if (name == NULL)
+ goto error_return;
/* If this symbol has line number information attached to it,
and we're not stripping it, count the number of entries and
@@ -1613,86 +1199,80 @@ xcoff_link_add_symbols (abfd, info)
we are going to attach line number information by symbol,
rather than by section, in order to more easily handle
garbage collection. */
- if ((info->strip == strip_none || info->strip == strip_some)
- && sym.n_numaux > 1
- && csect != NULL
- && ISFCN (sym.n_type))
- {
- union internal_auxent auxlin;
-
- bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
- sym.n_type, sym.n_sclass,
- 0, sym.n_numaux, (PTR) &auxlin);
- if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
- {
- asection *enclosing;
- bfd_size_type linoff;
-
- enclosing = xcoff_section_data (abfd, csect)->enclosing;
- if (enclosing == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: `%s' has line numbers but no enclosing section"),
- bfd_get_filename (abfd), name);
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
- linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
- - enclosing->line_filepos);
- if (linoff < enclosing->lineno_count * linesz)
- {
- struct internal_lineno lin;
- bfd_byte *linpstart;
-
- linpstart = (reloc_info[enclosing->target_index].linenos
- + linoff);
- bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
- if (lin.l_lnno == 0
- && ((bfd_size_type) lin.l_addr.l_symndx
- == ((esym
- - (bfd_byte *) obj_coff_external_syms (abfd))
- / symesz)))
- {
- bfd_byte *linpend, *linp;
+ if ((info->strip == strip_none || info->strip == strip_some) &&
+ (sym.n_numaux > 1) &&
+ (csect != NULL) &&
+ (ISFCN (sym.n_type))) {
- linpend = (reloc_info[enclosing->target_index].linenos
- + enclosing->lineno_count * linesz);
- for (linp = linpstart + linesz;
- linp < linpend;
- linp += linesz)
- {
- bfd_coff_swap_lineno_in (abfd, (PTR) linp,
- (PTR) &lin);
- if (lin.l_lnno == 0)
- break;
- }
- csect->lineno_count += (linp - linpstart) / linesz;
- /* The setting of line_filepos will only be
- useful if all the line number entries for a
- csect are contiguous; this only matters for
- error reporting. */
- if (csect->line_filepos == 0)
- csect->line_filepos =
- auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
- }
- }
- }
- }
-
- /* Pick up the csect auxiliary information. */
+ union internal_auxent auxlin;
- if (sym.n_numaux == 0)
- {
+ bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
+ sym.n_type, sym.n_sclass,
+ 0, sym.n_numaux, (PTR) &auxlin);
+
+ if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0) {
+ asection *enclosing;
+ bfd_signed_vma linoff;
+
+ enclosing = xcoff_section_data (abfd, csect)->enclosing;
+ if (enclosing == NULL) {
(*_bfd_error_handler)
- (_("%s: class %d symbol `%s' has no aux entries"),
- bfd_get_filename (abfd), sym.n_sclass, name);
+ (_("%s: `%s' has line numbers but no enclosing section"),
+ bfd_get_filename (abfd), name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
+ linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
+ - enclosing->line_filepos);
+ /* explict cast to bfd_signed_vma for compiler */
+ if (linoff < (bfd_signed_vma)(enclosing->lineno_count * linesz)) {
+ struct internal_lineno lin;
+ bfd_byte *linpstart;
+
+ linpstart = (reloc_info[enclosing->target_index].linenos
+ + linoff);
+ bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
+ if (lin.l_lnno == 0
+ && ((bfd_size_type) lin.l_addr.l_symndx
+ == ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz))) {
+ bfd_byte *linpend, *linp;
+
+ linpend = (reloc_info[enclosing->target_index].linenos
+ + enclosing->lineno_count * linesz);
+ for (linp = linpstart + linesz; linp < linpend; linp += linesz) {
+ bfd_coff_swap_lineno_in (abfd, (PTR) linp,
+ (PTR) &lin);
+ if (lin.l_lnno == 0)
+ break;
+ }
+ csect->lineno_count += (linp - linpstart) / linesz;
+ /* The setting of line_filepos will only be
+ useful if all the line number entries for a
+ csect are contiguous; this only matters for
+ error reporting. */
+ if (csect->line_filepos == 0)
+ csect->line_filepos =
+ auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ }
+ }
+ }
+ }
- bfd_coff_swap_aux_in (abfd,
- (PTR) (esym + symesz * sym.n_numaux),
- sym.n_type, sym.n_sclass,
+ /* Pick up the csect auxiliary information. */
+
+ if (sym.n_numaux == 0) {
+ (*_bfd_error_handler)
+ (_("%s: class %d symbol `%s' has no aux entries"),
+ bfd_get_filename (abfd), sym.n_sclass, name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ bfd_coff_swap_aux_in (abfd,
+ (PTR) (esym + symesz * sym.n_numaux),
+ sym.n_type, sym.n_sclass,
sym.n_numaux - 1, sym.n_numaux,
(PTR) &aux);
@@ -1739,7 +1319,6 @@ xcoff_link_add_symbols (abfd, info)
case XTY_SD:
/* This is a csect definition. */
-
if (csect != NULL)
{
xcoff_section_data (abfd, csect)->last_symndx =
@@ -1767,144 +1346,155 @@ xcoff_link_add_symbols (abfd, info)
xcoff_data (abfd)->toc = sym.n_value;
}
- /* We must merge TOC entries for the same symbol. We can
- merge two TOC entries if they are both C_HIDEXT, they
- both have the same name, they are both 4 bytes long, and
- they both have a relocation table entry for an external
- symbol with the same name. Unfortunately, this means
- that we must look through the relocations. Ick. */
- if (aux.x_csect.x_smclas == XMC_TC
- && sym.n_sclass == C_HIDEXT
- && aux.x_csect.x_scnlen.l == 4
- && info->hash->creator == abfd->xvec)
- {
- asection *enclosing;
- struct internal_reloc *relocs;
- bfd_size_type relindx;
- struct internal_reloc *rel;
+ /*
+ * We must merge TOC entries for the same symbol. We can
+ * merge two TOC entries if they are both C_HIDEXT, they
+ * both have the same name, they are both 4 or 8 bytes long, and
+ * they both have a relocation table entry for an external
+ * symbol with the same name. Unfortunately, this means
+ * that we must look through the relocations. Ick.
+ *
+ * Logic for 32 bit vs 64 bit.
+ * 32 bit has a csect length of 4 for TOC
+ * 64 bit has a csect length of 8 for TOC
+ *
+ * The conditions to get past the if-check are not that bad.
+ * They are what is used to create the TOC csects in the first
+ * place
+ */
+ if ((aux.x_csect.x_smclas == XMC_TC) &&
+ (sym.n_sclass == C_HIDEXT) &&
+ (info->hash->creator == abfd->xvec) &&
+ (((bfd_xcoff_is_xcoff32(abfd)) &&
+ (aux.x_csect.x_scnlen.l == 4)) ||
+ ((bfd_xcoff_is_xcoff64(abfd)) &&
+ (aux.x_csect.x_scnlen.l == 8)))) {
- enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
- if (enclosing == NULL)
- goto error_return;
-
- relocs = reloc_info[enclosing->target_index].relocs;
- relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
- sym.n_value);
- rel = relocs + relindx;
- if (relindx < enclosing->reloc_count
- && rel->r_vaddr == (bfd_vma) sym.n_value
- && rel->r_size == 31
- && rel->r_type == R_POS)
- {
- bfd_byte *erelsym;
- struct internal_syment relsym;
-
- erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
- + rel->r_symndx * symesz);
- bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
- if (relsym.n_sclass == C_EXT)
- {
- const char *relname;
- char relbuf[SYMNMLEN + 1];
- boolean copy;
- struct xcoff_link_hash_entry *h;
-
- /* At this point we know that the TOC entry is
- for an externally visible symbol. */
- relname = _bfd_coff_internal_syment_name (abfd, &relsym,
- relbuf);
- if (relname == NULL)
- goto error_return;
-
- /* We only merge TOC entries if the TC name is
- the same as the symbol name. This handles
- the normal case, but not common cases like
- SYM.P4 which gcc generates to store SYM + 4
- in the TOC. FIXME. */
- if (strcmp (name, relname) == 0)
- {
- copy = (! info->keep_memory
- || relsym._n._n_n._n_zeroes != 0
- || relsym._n._n_n._n_offset == 0);
- h = xcoff_link_hash_lookup (xcoff_hash_table (info),
- relname, true, copy,
- false);
- if (h == NULL)
- goto error_return;
-
- /* At this point h->root.type could be
- bfd_link_hash_new. That should be OK,
- since we know for sure that we will come
- across this symbol as we step through the
- file. */
-
- /* We store h in *sym_hash for the
- convenience of the relocate_section
- function. */
- *sym_hash = h;
+ asection *enclosing;
+ struct internal_reloc *relocs;
+ bfd_size_type relindx;
+ struct internal_reloc *rel;
- if (h->toc_section != NULL)
- {
- asection **rel_csects;
-
- /* We already have a TOC entry for this
- symbol, so we can just ignore this
- one. */
- rel_csects =
- reloc_info[enclosing->target_index].csects;
- rel_csects[relindx] = bfd_und_section_ptr;
- break;
- }
+ enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ if (enclosing == NULL)
+ goto error_return;
- /* We are about to create a TOC entry for
- this symbol. */
- set_toc = h;
- }
- }
- }
- }
+ relocs = reloc_info[enclosing->target_index].relocs;
+ relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+ sym.n_value);
+ rel = relocs + relindx;
+
+ /*
+ * 32 bit R_POS r_size is 31
+ * 64 bit R_POS r_size is 63
+ */
+ if ((relindx < enclosing->reloc_count) &&
+ (rel->r_vaddr == (bfd_vma) sym.n_value) &&
+ (rel->r_type == R_POS) &&
+ (((bfd_xcoff_is_xcoff32(abfd)) &&
+ (rel->r_size == 31)) ||
+ ((bfd_xcoff_is_xcoff64(abfd)) &&
+ (rel->r_size == 63)))) {
+
+ bfd_byte *erelsym;
+
+ struct internal_syment relsym;
+
+ erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
+ + rel->r_symndx * symesz);
+ bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
+ if (relsym.n_sclass == C_EXT) {
+ const char *relname;
+ char relbuf[SYMNMLEN + 1];
+ boolean copy;
+ struct xcoff_link_hash_entry *h;
+
+ /* At this point we know that the TOC entry is
+ for an externally visible symbol. */
+
+ relname = _bfd_coff_internal_syment_name (abfd, &relsym,
+ relbuf);
+ if (relname == NULL)
+ goto error_return;
+
+ /* We only merge TOC entries if the TC name is
+ the same as the symbol name. This handles
+ the normal case, but not common cases like
+ SYM.P4 which gcc generates to store SYM + 4
+ in the TOC. FIXME. */
+
+ if (strcmp (name, relname) == 0) {
+ copy = (! info->keep_memory
+ || relsym._n._n_n._n_zeroes != 0
+ || relsym._n._n_n._n_offset == 0);
+ h = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ relname, true, copy,
+ false);
+ if (h == NULL)
+ goto error_return;
+
+ /* At this point h->root.type could be
+ bfd_link_hash_new. That should be OK,
+ since we know for sure that we will come
+ across this symbol as we step through the
+ file. */
+
+ /* We store h in *sym_hash for the
+ convenience of the relocate_section
+ function. */
+ *sym_hash = h;
+
+ if (h->toc_section != NULL) {
+ asection **rel_csects;
+
+ /* We already have a TOC entry for this
+ symbol, so we can just ignore this
+ one. */
+ rel_csects =
+ reloc_info[enclosing->target_index].csects;
+ rel_csects[relindx] = bfd_und_section_ptr;
+ break;
+ }
+
+ /* We are about to create a TOC entry for
+ this symbol. */
+ set_toc = h;
+ } /* merge toc reloc */
+ } /* c_ext */
+ } /* reloc */
+ } /* merge toc */
- /* We need to create a new section. We get the name from
- the csect storage mapping class, so that the linker can
- accumulate similar csects together. */
{
- static const char *csect_name_by_class[] = {
- ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
- ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
- ".td"
- };
- const char *csect_name;
+
asection *enclosing;
- if ((aux.x_csect.x_smclas >=
- sizeof csect_name_by_class / sizeof csect_name_by_class[0])
- || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: symbol `%s' has unrecognized smclas %d"),
- bfd_get_filename (abfd), name, aux.x_csect.x_smclas);
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
+ /* We need to create a new section. We get the name from
+ the csect storage mapping class, so that the linker can
+ accumulate similar csects together. */
- csect_name = csect_name_by_class[aux.x_csect.x_smclas];
- csect = bfd_make_section_anyway (abfd, csect_name);
- if (csect == NULL)
+ csect = bfd_xcoff_create_csect_from_smclas(abfd, &aux, name);
+ if (NULL == csect) {
goto error_return;
+ }
+
+ /*
+ * The enclosing section is the main section : .data, .text
+ * or .bss that the csect is coming from
+ */
enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
if (enclosing == NULL)
goto error_return;
- if (! bfd_is_abs_section (enclosing)
- && ((bfd_vma) sym.n_value < enclosing->vma
- || ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
- > enclosing->vma + enclosing->_raw_size)))
- {
- (*_bfd_error_handler)
- (_("%s: csect `%s' not in enclosing section"),
- bfd_get_filename (abfd), name);
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
+
+ if (! bfd_is_abs_section (enclosing) &&
+ ((bfd_vma) sym.n_value < enclosing->vma ||
+ ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
+ > enclosing->vma + enclosing->_raw_size))) {
+ (*_bfd_error_handler)
+ (_("%s: csect `%s' not in enclosing section"),
+ bfd_get_filename (abfd), name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
csect->vma = sym.n_value;
csect->filepos = (enclosing->filepos
+ sym.n_value
@@ -1927,33 +1517,34 @@ xcoff_link_add_symbols (abfd, info)
xcoff_section_data (abfd, csect)->lineno_count =
enclosing->lineno_count;
- if (enclosing->owner == abfd)
- {
- struct internal_reloc *relocs;
- bfd_size_type relindx;
- struct internal_reloc *rel;
- asection **rel_csect;
-
- relocs = reloc_info[enclosing->target_index].relocs;
- relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
- csect->vma);
- rel = relocs + relindx;
- rel_csect = (reloc_info[enclosing->target_index].csects
- + relindx);
- csect->rel_filepos = (enclosing->rel_filepos
- + relindx * bfd_coff_relsz (abfd));
- while (relindx < enclosing->reloc_count
- && *rel_csect == NULL
- && rel->r_vaddr < csect->vma + csect->_raw_size)
- {
- *rel_csect = csect;
- csect->flags |= SEC_RELOC;
- ++csect->reloc_count;
- ++relindx;
- ++rel;
- ++rel_csect;
- }
+ if (enclosing->owner == abfd) {
+ struct internal_reloc *relocs;
+ bfd_size_type relindx;
+ struct internal_reloc *rel;
+ asection **rel_csect;
+
+ relocs = reloc_info[enclosing->target_index].relocs;
+ relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+ csect->vma);
+
+ rel = relocs + relindx;
+ rel_csect = (reloc_info[enclosing->target_index].csects
+ + relindx);
+
+ csect->rel_filepos = (enclosing->rel_filepos
+ + relindx * bfd_coff_relsz (abfd));
+ while (relindx < enclosing->reloc_count &&
+ *rel_csect == NULL &&
+ rel->r_vaddr < csect->vma + csect->_raw_size) {
+
+ *rel_csect = csect;
+ csect->flags |= SEC_RELOC;
+ ++csect->reloc_count;
+ ++relindx;
+ ++rel;
+ ++rel_csect;
}
+ }
/* There are a number of other fields and section flags
which we do not bother to set. */
@@ -2030,10 +1621,16 @@ xcoff_link_add_symbols (abfd, info)
/ symesz);
}
- if (aux.x_csect.x_smclas == XMC_TD)
- csect = bfd_make_section_anyway (abfd, ".tocbss");
- else
+ if (aux.x_csect.x_smclas == XMC_TD) {
+ /*
+ * The linker script puts the .td section in the data
+ * section after the .tc section
+ */
+ csect = bfd_make_section_anyway (abfd, ".td");
+
+ } else {
csect = bfd_make_section_anyway (abfd, ".bss");
+ }
if (csect == NULL)
goto error_return;
csect->vma = sym.n_value;
@@ -2072,32 +1669,31 @@ xcoff_link_add_symbols (abfd, info)
}
/* Check for magic symbol names. */
- if ((smtyp == XTY_SD || smtyp == XTY_CM)
- && aux.x_csect.x_smclas != XMC_TC
- && aux.x_csect.x_smclas != XMC_TD)
- {
- int i;
-
- i = -1;
- if (name[0] == '_')
- {
- if (strcmp (name, "_text") == 0)
- i = 0;
- else if (strcmp (name, "_etext") == 0)
- i = 1;
- else if (strcmp (name, "_data") == 0)
- i = 2;
- else if (strcmp (name, "_edata") == 0)
- i = 3;
- else if (strcmp (name, "_end") == 0)
- i = 4;
- }
- else if (name[0] == 'e' && strcmp (name, "end") == 0)
- i = 5;
-
- if (i != -1)
- xcoff_hash_table (info)->special_sections[i] = csect;
- }
+ if ((smtyp == XTY_SD || smtyp == XTY_CM) &&
+ (aux.x_csect.x_smclas != XMC_TC) &&
+ (aux.x_csect.x_smclas != XMC_TD)) {
+
+ int i = -1;
+
+ if (name[0] == '_') {
+ if (strcmp (name, "_text") == 0)
+ i = XCOFF_SPECIAL_SECTION_TEXT;
+ else if (strcmp (name, "_etext") == 0)
+ i = XCOFF_SPECIAL_SECTION_ETEXT;
+ else if (strcmp (name, "_data") == 0)
+ i = XCOFF_SPECIAL_SECTION_DATA;
+ else if (strcmp (name, "_edata") == 0)
+ i = XCOFF_SPECIAL_SECTION_EDATA;
+ else if (strcmp (name, "_end") == 0)
+ i = XCOFF_SPECIAL_SECTION_END;
+ } else if (name[0] == 'e' && strcmp (name, "end") == 0) {
+ i = XCOFF_SPECIAL_SECTION_END2;
+ }
+
+ if (i != -1) {
+ xcoff_hash_table (info)->special_sections[i] = csect;
+ }
+ }
/* Now we have enough information to add the symbol to the
linker hash table. */
@@ -2140,7 +1736,7 @@ xcoff_link_add_symbols (abfd, info)
shared object, which will cause symbol redefinitions,
although this is an easier case to detect. */
- if (info->hash->creator == abfd->xvec)
+ if (info->hash->creator == abfd->xvec)
{
if (! bfd_is_und_section (section))
*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
@@ -2262,11 +1858,11 @@ xcoff_link_add_symbols (abfd, info)
else
{
(*sym_hash)->root.u.c.p->alignment_power
- = csect->alignment_power;
+ = csect->alignment_power;
}
}
- if (info->hash->creator == abfd->xvec)
+ if (info->hash->creator == abfd->xvec)
{
int flag;
@@ -2310,8 +1906,10 @@ xcoff_link_add_symbols (abfd, info)
rel = reloc_info[o->target_index].relocs;
rel_csect = reloc_info[o->target_index].csects;
+
for (i = 0; i < o->reloc_count; i++, rel++, rel_csect++)
{
+
if (*rel_csect == NULL)
{
(*_bfd_error_handler)
@@ -2324,7 +1922,7 @@ xcoff_link_add_symbols (abfd, info)
/* We identify all symbols which are called, so that we
can create glue code for calls to functions imported
from dynamic objects. */
- if (info->hash->creator == abfd->xvec
+ if (info->hash->creator == abfd->xvec
&& *rel_csect != bfd_und_section_ptr
&& (rel->r_type == R_BR
|| rel->r_type == R_RBR)
@@ -2377,7 +1975,7 @@ xcoff_link_add_symbols (abfd, info)
/* Reset SEC_RELOC and the reloc_count, since the reloc
information is now attached to the csects. */
- o->flags &= ~SEC_RELOC;
+ o->flags &=~ SEC_RELOC;
o->reloc_count = 0;
/* If we are not keeping memory, free the reloc information. */
@@ -2434,10 +2032,10 @@ xcoff_link_add_dynamic_symbols (abfd, info)
struct bfd_link_info *info;
{
asection *lsec;
- bfd_byte *buf;
+ bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
- struct external_ldsym *elsym, *elsymend;
+ bfd_byte *elsym, *elsymend;
struct xcoff_import_file *n;
const char *bname;
const char *mname;
@@ -2447,15 +2045,15 @@ xcoff_link_add_dynamic_symbols (abfd, info)
/* We can only handle a dynamic object if we are generating an XCOFF
output file. */
- if (info->hash->creator != abfd->xvec)
+ if (info->hash->creator != abfd->xvec)
{
(*_bfd_error_handler)
(_("%s: XCOFF shared object when not producing XCOFF output"),
bfd_get_filename (abfd));
- bfd_set_error (bfd_error_invalid_operation);
+ bfd_set_error (bfd_error_invalid_operation);
return false;
}
-
+
/* The symbols we use from a dynamic object are not the symbols in
the normal symbol table, but, rather, the symbols in the export
table. If there is a global symbol in a dynamic object which is
@@ -2477,29 +2075,31 @@ xcoff_link_add_dynamic_symbols (abfd, info)
return false;
}
+
if (! xcoff_get_section_contents (abfd, lsec))
return false;
- buf = coff_section_data (abfd, lsec)->contents;
+ contents = coff_section_data (abfd, lsec)->contents;
/* Remove the sections from this object, so that they do not get
included in the link. */
abfd->sections = NULL;
- xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
+ bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
+
+ strings = (char *) contents + ldhdr.l_stoff;
+
+ elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
- strings = (char *) buf + ldhdr.l_stoff;
+ elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
- elsym = (struct external_ldsym *) (buf + LDHDRSZ);
- elsymend = elsym + ldhdr.l_nsyms;
- BFD_ASSERT (sizeof (struct external_ldsym) == LDSYMSZ);
- for (; elsym < elsymend; elsym++)
+ for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct xcoff_link_hash_entry *h;
- xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+ bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
@@ -2618,7 +2218,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
}
}
- if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
+ if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
@@ -2676,6 +2276,7 @@ xcoff_mark_symbol (info, h)
struct bfd_link_info *info;
struct xcoff_link_hash_entry *h;
{
+
if ((h->flags & XCOFF_MARK) != 0)
return true;
@@ -3150,28 +2751,6 @@ bfd_xcoff_record_link_assignment (output_bfd, info, name)
return true;
}
-/* This structure is used to pass information through
- xcoff_link_hash_traverse. */
-
-struct xcoff_loader_info {
- /* Set if a problem occurred. */
- boolean failed;
- /* Output BFD. */
- bfd *output_bfd;
- /* Link information structure. */
- struct bfd_link_info *info;
- /* Whether all defined symbols should be exported. */
- boolean export_defineds;
- /* Number of ldsym structures. */
- size_t ldsym_count;
- /* Size of string table. */
- size_t string_size;
- /* String table. */
- bfd_byte *strings;
- /* Allocated size of string table. */
- size_t string_alc;
-};
-
/* Build the .loader section. This is called by the XCOFF linker
emulation before_allocation routine. We must set the size of the
.loader section before the linker lays out the output file.
@@ -3221,12 +2800,12 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
struct bfd_strtab_hash *debug_strtab;
bfd_byte *debug_contents = NULL;
- if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
- {
- for (i = 0; i < 6; i++)
- special_sections[i] = NULL;
- return true;
- }
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour) {
+
+ for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
+ special_sections[i] = NULL;
+ return true;
+ }
ldinfo.failed = false;
ldinfo.output_bfd = output_bfd;
@@ -3244,16 +2823,79 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
- if (entry == NULL)
+ if (entry == NULL) {
hentry = NULL;
- else
- {
- hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
- false, false, true);
- if (hentry != NULL)
- hentry->flags |= XCOFF_ENTRY;
+ } else {
+ hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
+ false, false, true);
+ if (hentry != NULL)
+ hentry->flags |= XCOFF_ENTRY;
+ }
+
+ /* __rtinit */
+ if (info->init_function || info->fini_function) {
+ struct xcoff_link_hash_entry *hrtinit;
+ struct internal_ldsym *ldsym;
+
+ hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ "__rtinit",
+ false, false, true);
+ if (hrtinit != NULL) {
+ xcoff_mark_symbol (info, hrtinit);
+ hrtinit->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
+ } else {
+ (*_bfd_error_handler)
+ (_("error: undefined symbol __rtinit"));
+
+ return false;
}
+ /*
+ *
+ * __rtinit initalized here
+ * Some information, like the location of the .initfini seciton will
+ * be filled in later
+ *
+ * name or offset taken case of below with bfd_xcoff_put_ldsymbol_name
+ */
+ ldsym = (struct internal_ldsym *)
+ bfd_malloc(sizeof (struct internal_ldsym));
+
+ ldsym->l_value = 0; /* will be filled in later */
+ ldsym->l_scnum = 2; /* data section */
+ ldsym->l_smtype = XTY_SD; /* csect section definition */
+ ldsym->l_smclas = 5; /* .rw */
+ ldsym->l_ifile = 0; /* special system loader symbol */
+ ldsym->l_parm = 0; /* NA */
+
+ /*
+ * Force __rtinit to be the first symbol in the loader symbol table
+ * See xcoff_build_ldsyms
+ *
+ * The first 3 symbol table indices are reserved to indicate the data,
+ * text and bss sections.
+ */
+ BFD_ASSERT (0 == ldinfo.ldsym_count);
+
+ hrtinit->ldindx = 3;
+ ldinfo.ldsym_count = 1;
+ hrtinit->ldsym = ldsym;
+
+ if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
+ hrtinit->ldsym,
+ hrtinit->root.root.string)) {
+ return false;
+ }
+
+ /*
+ * This symbol is written out by xcoff_write_global_symbol
+ * Set stuff up so xcoff_write_global_symbol logic works.
+ */
+ hrtinit->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
+ hrtinit->root.type = bfd_link_hash_defined;
+ hrtinit->root.u.def.value = 0;
+ }
+
/* Garbage collect unused sections. */
if (info->relocateable
|| ! gc
@@ -3289,23 +2931,22 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
}
/* Return special sections to the caller. */
- for (i = 0; i < 6; i++)
- {
- asection *sec;
-
- sec = xcoff_hash_table (info)->special_sections[i];
- if (sec != NULL
- && gc
- && (sec->flags & SEC_MARK) == 0)
- sec = NULL;
- special_sections[i] = sec;
+ for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++) {
+ asection *sec;
+
+ sec = xcoff_hash_table (info)->special_sections[i];
+
+ if ((sec != NULL) &&
+ (gc && (sec->flags & SEC_MARK) == 0)) {
+ sec = NULL;
}
+ special_sections[i] = sec;
+ }
- if (info->input_bfds == NULL)
- {
- /* I'm not sure what to do in this bizarre case. */
- return true;
- }
+ if (info->input_bfds == NULL) {
+ /* I'm not sure what to do in this bizarre case. */
+ return true;
+ }
xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
(PTR) &ldinfo);
@@ -3331,14 +2972,14 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
/* Set up the .loader section header. */
ldhdr = &xcoff_hash_table (info)->ldhdr;
- ldhdr->l_version = 1;
+ ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
ldhdr->l_nsyms = ldinfo.ldsym_count;
ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
ldhdr->l_istlen = impsize;
ldhdr->l_nimpid = impcount;
- ldhdr->l_impoff = (LDHDRSZ
- + ldhdr->l_nsyms * LDSYMSZ
- + ldhdr->l_nreloc * LDRELSZ);
+ ldhdr->l_impoff = (bfd_xcoff_ldhdrsz(output_bfd)
+ + ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd)
+ + ldhdr->l_nreloc * bfd_xcoff_ldrelsz(output_bfd));
ldhdr->l_stlen = ldinfo.string_size;
stoff = ldhdr->l_impoff + impsize;
if (ldinfo.string_size == 0)
@@ -3346,6 +2987,15 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
else
ldhdr->l_stoff = stoff;
+ /*
+ * 64 bit elements to ldhdr
+ * The swap out routine for 32 bit will ignore them.
+ * Nothing fancy, symbols come after the header and relocs come after symbols
+ */
+ ldhdr->l_symoff = bfd_xcoff_ldhdrsz(output_bfd);
+ ldhdr->l_rldoff = bfd_xcoff_ldhdrsz(output_bfd) +
+ (ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd));
+
/* We now know the final size of the .loader section. Allocate
space for it. */
lsec = xcoff_hash_table (info)->loader_section;
@@ -3355,8 +3005,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
goto error_return;
/* Set up the header. */
- xcoff_swap_ldhdr_out (output_bfd, ldhdr,
- (struct external_ldhdr *) lsec->contents);
+ bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
/* Set up the import file names. */
out = (char *) lsec->contents + ldhdr->l_impoff;
@@ -3395,7 +3044,8 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
symbols are written out in xcoff_link_input_bfd or
xcoff_write_global_symbol. The .loader relocs are written out
when the corresponding normal relocs are handled in
- xcoff_link_input_bfd. */
+ xcoff_link_input_bfd.
+ */
/* Allocate space for the magic sections. */
sec = xcoff_hash_table (info)->linkage_section;
@@ -3540,7 +3190,15 @@ xcoff_build_ldsyms (h, p)
PTR p;
{
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
- size_t len;
+
+ /*
+ * __rtinit
+ * Special handling of this symbol to make is the first symbol in the
+ * loader symbol table. Make sure this pass through does not undo it
+ */
+ if (h->flags & XCOFF_RTINIT) {
+ return true;
+ }
/* If this is a final link, and the symbol was defined as a common
symbol in a regular object file, and there was no definition in
@@ -3638,7 +3296,7 @@ xcoff_build_ldsyms (h, p)
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_GL;
h->flags |= XCOFF_DEF_REGULAR;
- sec->_raw_size += XCOFF_GLINK_SIZE;
+ sec->_raw_size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
/* The global linkage code requires a TOC entry for the
descriptor. */
@@ -3647,20 +3305,36 @@ xcoff_build_ldsyms (h, p)
|| hds->root.type == bfd_link_hash_undefweak)
&& (hds->flags & XCOFF_DEF_REGULAR) == 0);
hds->flags |= XCOFF_MARK;
- if (hds->toc_section == NULL)
- {
- hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
- hds->u.toc_offset = hds->toc_section->_raw_size;
- hds->toc_section->_raw_size += 4;
- ++xcoff_hash_table (ldinfo->info)->ldrel_count;
- ++hds->toc_section->reloc_count;
- hds->indx = -2;
- hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
-
- /* We need to call xcoff_build_ldsyms recursively here,
- because we may already have passed hds on the traversal. */
- xcoff_build_ldsyms (hds, p);
+ if (hds->toc_section == NULL) {
+ int byte_size;
+
+ /*
+ * 32 vs 64
+ * xcoff32 uses 4 bytes in the toc
+ * xcoff64 uses 8 bytes in the toc
+ */
+ if (bfd_xcoff_is_xcoff64(ldinfo->output_bfd)) {
+ byte_size = 8;
+ } else if (bfd_xcoff_is_xcoff32(ldinfo->output_bfd)) {
+ byte_size = 4;
+ } else {
+ return false;
}
+
+ hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
+ hds->u.toc_offset = hds->toc_section->_raw_size;
+ hds->toc_section->_raw_size += byte_size;
+ ++xcoff_hash_table (ldinfo->info)->ldrel_count;
+ ++hds->toc_section->reloc_count;
+ hds->indx = -2;
+ hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+
+ /*
+ * We need to call xcoff_build_ldsyms recursively here,
+ * because we may already have passed hds on the traversal.
+ */
+ xcoff_build_ldsyms (hds, p);
+ }
}
/* If this symbol is exported, but not defined, we need to try to
@@ -3689,15 +3363,25 @@ xcoff_build_ldsyms (h, p)
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_DS;
h->flags |= XCOFF_DEF_REGULAR;
- sec->_raw_size += 12;
- /* A function descriptor uses two relocs: one for the
- associated code, and one for the TOC address. */
+ /*
+ * The size of the function descriptor depends if this is an
+ * xcoff32 (12) or xcoff64 (24)
+ */
+ sec->_raw_size +=
+ bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
+
+ /*
+ * A function descriptor uses two relocs: one for the
+ * associated code, and one for the TOC address.
+ */
xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
sec->reloc_count += 2;
- /* We handle writing out the contents of the descriptor in
- xcoff_write_global_symbol. */
+ /*
+ * We handle writing out the contents of the descriptor in
+ * xcoff_write_global_symbol.
+ */
}
else
{
@@ -3766,46 +3450,19 @@ xcoff_build_ldsyms (h, p)
if ((h->flags & XCOFF_IMPORT) != 0)
h->ldsym->l_ifile = h->ldindx;
- /* The first 3 symbol table indices are reserved to indicate the
- sections. */
+ /*
+ * The first 3 symbol table indices are reserved to indicate the data,
+ * text and bss sections.
+ */
h->ldindx = ldinfo->ldsym_count + 3;
++ldinfo->ldsym_count;
- len = strlen (h->root.root.string);
- if (len <= SYMNMLEN)
- strncpy (h->ldsym->_l._l_name, h->root.root.string, SYMNMLEN);
- else
- {
- if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
- {
- size_t newalc;
- bfd_byte *newstrings;
-
- newalc = ldinfo->string_alc * 2;
- if (newalc == 0)
- newalc = 32;
- while (ldinfo->string_size + len + 3 > newalc)
- newalc *= 2;
-
- newstrings = ((bfd_byte *)
- bfd_realloc ((PTR) ldinfo->strings, newalc));
- if (newstrings == NULL)
- {
- ldinfo->failed = true;
- return false;
- }
- ldinfo->string_alc = newalc;
- ldinfo->strings = newstrings;
- }
-
- bfd_put_16 (ldinfo->output_bfd, len + 1,
- ldinfo->strings + ldinfo->string_size);
- strcpy (ldinfo->strings + ldinfo->string_size + 2, h->root.root.string);
- h->ldsym->_l._l_l._l_zeroes = 0;
- h->ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
- ldinfo->string_size += len + 3;
- }
+ if (false == bfd_xcoff_put_ldsymbol_name (ldinfo->output_bfd, ldinfo,
+ h->ldsym,
+ h->root.root.string)) {
+ return false;
+ }
h->flags |= XCOFF_BUILT_LDSYM;
@@ -3854,13 +3511,11 @@ _bfd_xcoff_bfd_final_link (abfd, info)
finfo.contents = NULL;
finfo.external_relocs = NULL;
- finfo.ldsym = ((struct external_ldsym *)
- (xcoff_hash_table (info)->loader_section->contents
- + LDHDRSZ));
- finfo.ldrel = ((struct external_ldrel *)
- (xcoff_hash_table (info)->loader_section->contents
- + LDHDRSZ
- + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
+ finfo.ldsym = xcoff_hash_table (info)->loader_section->contents +
+ bfd_xcoff_ldhdrsz(abfd);
+ finfo.ldrel = xcoff_hash_table (info)->loader_section->contents +
+ bfd_xcoff_ldhdrsz(abfd) +
+ xcoff_hash_table (info)->ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
xcoff_data (abfd)->coff.link_info = info;
@@ -3980,10 +3635,16 @@ _bfd_xcoff_bfd_final_link (abfd, info)
sofar = bfd_coff_filhsz (abfd);
sofar += bfd_coff_aoutsz (abfd);
sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
- for (o = abfd->sections; o != NULL; o = o->next)
- if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)
- sofar += bfd_coff_scnhsz (abfd);
+ for (o = abfd->sections; o != NULL; o = o->next) {
+ if ((true ==
+ bfd_xcoff_is_reloc_count_overflow(abfd, o->reloc_count)) ||
+ (true ==
+ bfd_xcoff_is_lineno_count_overflow(abfd, o->lineno_count))) {
+ /* 64 does not overflow, need to check if 32 does */
+ sofar += bfd_coff_scnhsz (abfd);
+ }
+ }
for (o = abfd->sections; o != NULL; o = o->next)
{
if (strcmp (o->name, ".pad") == 0)
@@ -4125,6 +3786,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
finfo.internal_syms = ((struct internal_syment *)
bfd_malloc (max_sym_count
* sizeof (struct internal_syment)));
+
finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
finfo.outsyms = ((bfd_byte *)
bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
@@ -4177,48 +3839,53 @@ _bfd_xcoff_bfd_final_link (abfd, info)
}
}
+
/* Free up the buffers used by xcoff_link_input_bfd. */
- if (finfo.internal_syms != NULL)
- {
- free (finfo.internal_syms);
- finfo.internal_syms = NULL;
- }
- if (finfo.sym_indices != NULL)
- {
- free (finfo.sym_indices);
- finfo.sym_indices = NULL;
- }
- if (finfo.linenos != NULL)
- {
- free (finfo.linenos);
- finfo.linenos = NULL;
- }
- if (finfo.contents != NULL)
- {
- free (finfo.contents);
- finfo.contents = NULL;
- }
- if (finfo.external_relocs != NULL)
- {
- free (finfo.external_relocs);
- finfo.external_relocs = NULL;
- }
+ if (finfo.internal_syms != NULL) {
+ free (finfo.internal_syms);
+ finfo.internal_syms = NULL;
+ }
+ if (finfo.sym_indices != NULL) {
+ free (finfo.sym_indices);
+ finfo.sym_indices = NULL;
+ }
+ if (finfo.linenos != NULL) {
+ free (finfo.linenos);
+ finfo.linenos = NULL;
+ }
+ if (finfo.contents != NULL) {
+ free (finfo.contents);
+ finfo.contents = NULL;
+ }
+ if (finfo.external_relocs != NULL) {
+ free (finfo.external_relocs);
+ finfo.external_relocs = NULL;
+ }
/* The value of the last C_FILE symbol is supposed to be -1. Write
it out again. */
- if (finfo.last_file_index != -1)
- {
- finfo.last_file.n_value = -1;
- bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
- (PTR) finfo.outsyms);
- if (bfd_seek (abfd,
- (obj_sym_filepos (abfd)
- + finfo.last_file_index * symesz),
- SEEK_SET) != 0
- || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
- goto error_return;
- }
+ if (finfo.last_file_index != -1) {
+ finfo.last_file.n_value = -1;
+ bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
+ (PTR) finfo.outsyms);
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + finfo.last_file_index * symesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
+ goto error_return;
+ }
+
+ /* init-fini */
+ if (info->init_function || info->fini_function) {
+ struct xcoff_link_hash_entry *hrtinit;
+
+ hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ "__rtinit",
+ false, false, true);
+ }
+
/* Write out all the global symbols which do not come from XCOFF
input files. */
@@ -4239,100 +3906,90 @@ _bfd_xcoff_bfd_final_link (abfd, info)
if (external_relocs == NULL && max_output_reloc_count != 0)
goto error_return;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- struct internal_reloc *irel;
- struct internal_reloc *irelend;
- struct xcoff_link_hash_entry **rel_hash;
- struct xcoff_toc_rel_hash *toc_rel_hash;
- bfd_byte *erel;
-
- /* A stripped file has no relocs. */
- if (info->strip == strip_all)
- {
- o->reloc_count = 0;
- continue;
- }
-
- if (o->reloc_count == 0)
- continue;
-
- irel = finfo.section_info[o->target_index].relocs;
- irelend = irel + o->reloc_count;
- rel_hash = finfo.section_info[o->target_index].rel_hashes;
- for (; irel < irelend; irel++, rel_hash++, erel += relsz)
- {
- if (*rel_hash != NULL)
- {
- if ((*rel_hash)->indx < 0)
- {
- if (! ((*info->callbacks->unattached_reloc)
- (info, (*rel_hash)->root.root.string,
- (bfd *) NULL, o, irel->r_vaddr)))
- goto error_return;
- (*rel_hash)->indx = 0;
- }
- irel->r_symndx = (*rel_hash)->indx;
- }
- }
-
- for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
- toc_rel_hash != NULL;
- toc_rel_hash = toc_rel_hash->next)
- {
- if (toc_rel_hash->h->u.toc_indx < 0)
- {
- if (! ((*info->callbacks->unattached_reloc)
- (info, toc_rel_hash->h->root.root.string,
- (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
- goto error_return;
- toc_rel_hash->h->u.toc_indx = 0;
- }
- toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
+ for (o = abfd->sections; o != NULL; o = o->next) {
+ struct internal_reloc *irel;
+ struct internal_reloc *irelend;
+ struct xcoff_link_hash_entry **rel_hash;
+ struct xcoff_toc_rel_hash *toc_rel_hash;
+ bfd_byte *erel;
+
+ /* A stripped file has no relocs. */
+ if (info->strip == strip_all) {
+ o->reloc_count = 0;
+ continue;
+ }
+
+ if (o->reloc_count == 0)
+ continue;
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = finfo.section_info[o->target_index].rel_hashes;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz) {
+ if (*rel_hash != NULL) {
+ if ((*rel_hash)->indx < 0) {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, (*rel_hash)->root.root.string,
+ (bfd *) NULL, o, irel->r_vaddr)))
+ goto error_return;
+ (*rel_hash)->indx = 0;
}
-
- /* XCOFF requires that the relocs be sorted by address. We tend
- to produce them in the order in which their containing csects
- appear in the symbol table, which is not necessarily by
- address. So we sort them here. There may be a better way to
- do this. */
- qsort ((PTR) finfo.section_info[o->target_index].relocs,
- o->reloc_count, sizeof (struct internal_reloc),
- xcoff_sort_relocs);
-
- irel = finfo.section_info[o->target_index].relocs;
- irelend = irel + o->reloc_count;
- erel = external_relocs;
- for (; irel < irelend; irel++, rel_hash++, erel += relsz)
- bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
-
- if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
- || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
- abfd) != relsz * o->reloc_count)
- goto error_return;
+ irel->r_symndx = (*rel_hash)->indx;
+ }
}
- if (external_relocs != NULL)
- {
- free (external_relocs);
- external_relocs = NULL;
+ for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
+ toc_rel_hash != NULL;
+ toc_rel_hash = toc_rel_hash->next) {
+ if (toc_rel_hash->h->u.toc_indx < 0) {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, toc_rel_hash->h->root.root.string,
+ (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
+ goto error_return;
+ toc_rel_hash->h->u.toc_indx = 0;
+ }
+ toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
}
+ /* XCOFF requires that the relocs be sorted by address. We tend
+ to produce them in the order in which their containing csects
+ appear in the symbol table, which is not necessarily by
+ address. So we sort them here. There may be a better way to
+ do this. */
+ qsort ((PTR) finfo.section_info[o->target_index].relocs,
+ o->reloc_count, sizeof (struct internal_reloc),
+ xcoff_sort_relocs);
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ erel = external_relocs;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+ || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+ abfd) != relsz * o->reloc_count)
+ goto error_return;
+ }
+
+ if (external_relocs != NULL) {
+ free (external_relocs);
+ external_relocs = NULL;
+ }
+
/* Free up the section information. */
- if (finfo.section_info != NULL)
- {
- unsigned int i;
+ if (finfo.section_info != NULL) {
+ unsigned int i;
- for (i = 0; i < abfd->section_count; i++)
- {
- if (finfo.section_info[i].relocs != NULL)
- free (finfo.section_info[i].relocs);
- if (finfo.section_info[i].rel_hashes != NULL)
- free (finfo.section_info[i].rel_hashes);
- }
- free (finfo.section_info);
- finfo.section_info = NULL;
+ for (i = 0; i < abfd->section_count; i++) {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
}
+ free (finfo.section_info);
+ finfo.section_info = NULL;
+ }
/* Write out the loader section contents. */
BFD_ASSERT ((bfd_byte *) finfo.ldrel
@@ -4379,43 +4036,42 @@ _bfd_xcoff_bfd_final_link (abfd, info)
/* Write out the debugging string table. */
o = xcoff_hash_table (info)->debug_section;
- if (o != NULL)
- {
- struct bfd_strtab_hash *debug_strtab;
-
- debug_strtab = xcoff_hash_table (info)->debug_strtab;
- BFD_ASSERT (o->output_section->_raw_size - o->output_offset
- >= _bfd_stringtab_size (debug_strtab));
- if (bfd_seek (abfd,
- o->output_section->filepos + o->output_offset,
- SEEK_SET) != 0)
- goto error_return;
- if (! _bfd_stringtab_emit (abfd, debug_strtab))
- goto error_return;
- }
-
+ if (o != NULL) {
+ struct bfd_strtab_hash *debug_strtab;
+
+ debug_strtab = xcoff_hash_table (info)->debug_strtab;
+ BFD_ASSERT (o->output_section->_raw_size - o->output_offset
+ >= _bfd_stringtab_size (debug_strtab));
+ if (bfd_seek (abfd,
+ o->output_section->filepos + o->output_offset,
+ SEEK_SET) != 0)
+ goto error_return;
+ if (! _bfd_stringtab_emit (abfd, debug_strtab))
+ goto error_return;
+ }
+
/* Setting bfd_get_symcount to 0 will cause write_object_contents to
not try to write out the symbols. */
bfd_get_symcount (abfd) = 0;
-
+
return true;
error_return:
if (finfo.strtab != NULL)
_bfd_stringtab_free (finfo.strtab);
- if (finfo.section_info != NULL)
- {
- unsigned int i;
-
- for (i = 0; i < abfd->section_count; i++)
- {
- if (finfo.section_info[i].relocs != NULL)
- free (finfo.section_info[i].relocs);
- if (finfo.section_info[i].rel_hashes != NULL)
- free (finfo.section_info[i].rel_hashes);
- }
- free (finfo.section_info);
+
+ if (finfo.section_info != NULL) {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++) {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
}
+ free (finfo.section_info);
+ }
+
if (finfo.internal_syms != NULL)
free (finfo.internal_syms);
if (finfo.sym_indices != NULL)
@@ -4510,6 +4166,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
while (esym < esym_end)
{
+
struct internal_syment isym;
union internal_auxent aux;
int smtyp = 0;
@@ -4529,6 +4186,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
isymp->n_type, isymp->n_sclass,
isymp->n_numaux - 1, isymp->n_numaux,
(PTR) &aux);
+
smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
}
@@ -4613,17 +4271,18 @@ xcoff_link_input_bfd (finfo, input_bfd)
ldsym->l_parm = 0;
BFD_ASSERT (h->ldindx >= 0);
- BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
- xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
- finfo->ldsym + h->ldindx - 3);
+ bfd_xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
+ finfo->ldsym + (h->ldindx - 3) *
+ bfd_xcoff_ldsymsz(finfo->output_bfd));
h->ldsym = NULL;
/* Fill in snentry now that we know the target_index. */
- if ((h->flags & XCOFF_ENTRY) != 0
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
+ if ((h->flags & XCOFF_ENTRY) != 0 &&
+ (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)) {
xcoff_data (output_bfd)->snentry =
h->root.u.def.section->output_section->target_index;
+ }
}
*indexp = -1;
@@ -4716,6 +4375,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
xcoff_data (finfo->output_bfd)->sntoc =
(*csectpp)->output_section->target_index;
require = true;
+
}
}
@@ -4771,6 +4431,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
char buf[SYMNMLEN + 1];
name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+
if (name == NULL)
return false;
@@ -4811,6 +4472,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
name = _bfd_coff_internal_syment_name (input_bfd, &isym,
(char *) NULL);
+
if (name == NULL)
return false;
indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
@@ -4839,7 +4501,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
if (isym.n_sclass == C_FILE)
{
if (finfo->last_file_index != -1
- && finfo->last_file.n_value != (long) output_index)
+ && finfo->last_file.n_value != (bfd_vma) output_index)
{
/* We must correct the value of the last C_FILE entry. */
finfo->last_file.n_value = output_index;
@@ -4956,7 +4618,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
if (isymp->n_sclass == C_BSTAT)
{
struct internal_syment isym;
- unsigned long indx;
+
+ bfd_vma indx;
/* The value of a C_BSTAT symbol is the symbol table
index of the containing csect. */
@@ -5018,6 +4681,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
|| isymp->n_sclass == C_HIDEXT)
&& i + 1 == isymp->n_numaux)
{
+
/* We don't support type checking. I don't know if
anybody does. */
aux.x_csect.x_parmhash = 0;
@@ -5025,20 +4689,23 @@ xcoff_link_input_bfd (finfo, input_bfd)
better clobber them just in case. */
aux.x_csect.x_stab = 0;
aux.x_csect.x_snstab = 0;
+
if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
{
- unsigned long indx;
+ bfd_signed_vma indx;
+
- indx = aux.x_csect.x_scnlen.l;
+ indx = aux.x_csect.x_scnlen.l;
if (indx < obj_raw_syment_count (input_bfd))
{
long symindx;
symindx = finfo->sym_indices[indx];
- if (symindx < 0)
- aux.x_sym.x_tagndx.l = 0;
- else
- aux.x_sym.x_tagndx.l = symindx;
+ if (symindx < 0) {
+ aux.x_csect.x_scnlen.l = 0;
+ } else {
+ aux.x_csect.x_scnlen.l = symindx;
+ }
}
}
}
@@ -5067,6 +4734,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
else
indx = finfo->sym_indices[indx];
aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+
}
}
@@ -5081,6 +4749,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
else
aux.x_sym.x_tagndx.l = symindx;
}
+
}
/* Copy over the line numbers, unless we are stripping
@@ -5100,7 +4769,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
{
asection *enclosing;
unsigned int enc_count;
- bfd_size_type linoff;
+ bfd_signed_vma linoff;
struct internal_lineno lin;
o = *csectpp;
@@ -5199,7 +4868,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
&& (iisp->n_sclass == C_BINCL
|| iisp->n_sclass == C_EINCL)
&& ((bfd_size_type) iisp->n_value
- >= enclosing->line_filepos + linoff)
+ >= (bfd_size_type)(enclosing->line_filepos + linoff))
&& ((bfd_size_type) iisp->n_value
< (enclosing->line_filepos
+ enc_count * linesz)))
@@ -5281,319 +4950,318 @@ xcoff_link_input_bfd (finfo, input_bfd)
obj_coff_keep_syms (input_bfd) = true;
/* Relocate the contents of each section. */
- for (o = input_bfd->sections; o != NULL; o = o->next)
- {
- bfd_byte *contents;
+ for (o = input_bfd->sections; o != NULL; o = o->next) {
+
+ bfd_byte *contents;
- if (! o->linker_mark)
- {
- /* This section was omitted from the link. */
- continue;
- }
+ if (! o->linker_mark){
+ /* This section was omitted from the link. */
+ continue;
+ }
- if ((o->flags & SEC_HAS_CONTENTS) == 0
- || o->_raw_size == 0
- || (o->flags & SEC_IN_MEMORY) != 0)
- continue;
+ if ((o->flags & SEC_HAS_CONTENTS) == 0
+ || o->_raw_size == 0
+ || (o->flags & SEC_IN_MEMORY) != 0)
+ continue;
+
+ /* We have set filepos correctly for the sections we created to
+ represent csects, so bfd_get_section_contents should work. */
+ if (coff_section_data (input_bfd, o) != NULL
+ && coff_section_data (input_bfd, o)->contents != NULL)
+ contents = coff_section_data (input_bfd, o)->contents;
+ else {
+ if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
+ (file_ptr) 0, o->_raw_size))
+ return false;
+ contents = finfo->contents;
+ }
- /* We have set filepos correctly for the sections we created to
- represent csects, so bfd_get_section_contents should work. */
- if (coff_section_data (input_bfd, o) != NULL
- && coff_section_data (input_bfd, o)->contents != NULL)
- contents = coff_section_data (input_bfd, o)->contents;
- else
- {
- if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
- (file_ptr) 0, o->_raw_size))
- return false;
- contents = finfo->contents;
- }
+ if ((o->flags & SEC_RELOC) != 0) {
+ int target_index;
+ struct internal_reloc *internal_relocs;
+ struct internal_reloc *irel;
+ bfd_vma offset;
+ struct internal_reloc *irelend;
+ struct xcoff_link_hash_entry **rel_hash;
+ long r_symndx;
+
+ /* Read in the relocs. */
+ target_index = o->output_section->target_index;
+ internal_relocs = (xcoff_read_internal_relocs
+ (input_bfd, o, false, finfo->external_relocs,
+ true,
+ (finfo->section_info[target_index].relocs
+ + o->output_section->reloc_count)));
+ if (internal_relocs == NULL)
+ return false;
- if ((o->flags & SEC_RELOC) != 0)
- {
- int target_index;
- struct internal_reloc *internal_relocs;
- struct internal_reloc *irel;
- bfd_vma offset;
- struct internal_reloc *irelend;
- struct xcoff_link_hash_entry **rel_hash;
- long r_symndx;
-
- /* Read in the relocs. */
- target_index = o->output_section->target_index;
- internal_relocs = (xcoff_read_internal_relocs
- (input_bfd, o, false, finfo->external_relocs,
- true,
- (finfo->section_info[target_index].relocs
- + o->output_section->reloc_count)));
- if (internal_relocs == NULL)
- return false;
+ /* Call processor specific code to relocate the section
+ contents. */
+ if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+ input_bfd, o,
+ contents,
+ internal_relocs,
+ finfo->internal_syms,
+ xcoff_data (input_bfd)->csects))
+ return false;
- /* Call processor specific code to relocate the section
- contents. */
- if (! bfd_coff_relocate_section (output_bfd, finfo->info,
- input_bfd, o,
- contents,
- internal_relocs,
- finfo->internal_syms,
- xcoff_data (input_bfd)->csects))
- return false;
+ offset = o->output_section->vma + o->output_offset - o->vma;
+ irel = internal_relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = (finfo->section_info[target_index].rel_hashes
+ + o->output_section->reloc_count);
+ for (; irel < irelend; irel++, rel_hash++) {
+ struct xcoff_link_hash_entry *h = NULL;
+ struct internal_ldrel ldrel;
+ boolean quiet;
- offset = o->output_section->vma + o->output_offset - o->vma;
- irel = internal_relocs;
- irelend = irel + o->reloc_count;
- rel_hash = (finfo->section_info[target_index].rel_hashes
- + o->output_section->reloc_count);
- for (; irel < irelend; irel++, rel_hash++)
- {
- struct xcoff_link_hash_entry *h = NULL;
- struct internal_ldrel ldrel;
- boolean quiet;
+ *rel_hash = NULL;
- *rel_hash = NULL;
+ /* Adjust the reloc address and symbol index. */
- /* Adjust the reloc address and symbol index. */
+ irel->r_vaddr += offset;
- irel->r_vaddr += offset;
+ r_symndx = irel->r_symndx;
- r_symndx = irel->r_symndx;
+ if (r_symndx == -1)
+ h = NULL;
+ else
+ h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
- if (r_symndx == -1)
- h = NULL;
- else
- h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
+ if (r_symndx != -1 && finfo->info->strip != strip_all)
+ {
+ if (h != NULL
+ && h->smclas != XMC_TD
+ && (irel->r_type == R_TOC
+ || irel->r_type == R_GL
+ || irel->r_type == R_TCL
+ || irel->r_type == R_TRL
+ || irel->r_type == R_TRLA))
+ {
+ /* This is a TOC relative reloc with a symbol
+ attached. The symbol should be the one which
+ this reloc is for. We want to make this
+ reloc against the TOC address of the symbol,
+ not the symbol itself. */
+ BFD_ASSERT (h->toc_section != NULL);
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ if (h->u.toc_indx != -1)
+ irel->r_symndx = h->u.toc_indx;
+ else
+ {
+ struct xcoff_toc_rel_hash *n;
+ struct xcoff_link_section_info *si;
- if (r_symndx != -1 && finfo->info->strip != strip_all)
- {
- if (h != NULL
- && h->smclas != XMC_TD
- && (irel->r_type == R_TOC
- || irel->r_type == R_GL
- || irel->r_type == R_TCL
- || irel->r_type == R_TRL
- || irel->r_type == R_TRLA))
- {
- /* This is a TOC relative reloc with a symbol
- attached. The symbol should be the one which
- this reloc is for. We want to make this
- reloc against the TOC address of the symbol,
- not the symbol itself. */
- BFD_ASSERT (h->toc_section != NULL);
- BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
- if (h->u.toc_indx != -1)
- irel->r_symndx = h->u.toc_indx;
- else
- {
- struct xcoff_toc_rel_hash *n;
- struct xcoff_link_section_info *si;
+ n = ((struct xcoff_toc_rel_hash *)
+ bfd_alloc (finfo->output_bfd,
+ sizeof (struct xcoff_toc_rel_hash)));
+ if (n == NULL)
+ return false;
+ si = finfo->section_info + target_index;
+ n->next = si->toc_rel_hashes;
+ n->h = h;
+ n->rel = irel;
+ si->toc_rel_hashes = n;
+ }
+ }
+ else if (h != NULL)
+ {
+ /* This is a global symbol. */
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ /* This symbol is being written at the end
+ of the file, and we do not yet know the
+ symbol index. We save the pointer to the
+ hash table entry in the rel_hash list.
+ We set the indx field to -2 to indicate
+ that this symbol must not be stripped. */
+ *rel_hash = h;
+ h->indx = -2;
+ }
+ }
+ else
+ {
+ long indx;
- n = ((struct xcoff_toc_rel_hash *)
- bfd_alloc (finfo->output_bfd,
- sizeof (struct xcoff_toc_rel_hash)));
- if (n == NULL)
- return false;
- si = finfo->section_info + target_index;
- n->next = si->toc_rel_hashes;
- n->h = h;
- n->rel = irel;
- si->toc_rel_hashes = n;
- }
- }
- else if (h != NULL)
- {
- /* This is a global symbol. */
- if (h->indx >= 0)
- irel->r_symndx = h->indx;
- else
- {
- /* This symbol is being written at the end
- of the file, and we do not yet know the
- symbol index. We save the pointer to the
- hash table entry in the rel_hash list.
- We set the indx field to -2 to indicate
- that this symbol must not be stripped. */
- *rel_hash = h;
- h->indx = -2;
- }
- }
- else
- {
- long indx;
+ indx = finfo->sym_indices[r_symndx];
- indx = finfo->sym_indices[r_symndx];
+ if (indx == -1)
+ {
+ struct internal_syment *is;
+
+ /* Relocations against a TC0 TOC anchor are
+ automatically transformed to be against
+ the TOC anchor in the output file. */
+ is = finfo->internal_syms + r_symndx;
+ if (is->n_sclass == C_HIDEXT
+ && is->n_numaux > 0)
+ {
+ PTR auxptr;
+ union internal_auxent aux;
+
+ auxptr = ((PTR)
+ (((bfd_byte *)
+ obj_coff_external_syms (input_bfd))
+ + ((r_symndx + is->n_numaux)
+ * isymesz)));
+ bfd_coff_swap_aux_in (input_bfd, auxptr,
+ is->n_type, is->n_sclass,
+ is->n_numaux - 1,
+ is->n_numaux,
+ (PTR) &aux);
+ if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
+ && aux.x_csect.x_smclas == XMC_TC0)
+ indx = finfo->toc_symindx;
+ }
+ }
- if (indx == -1)
- {
- struct internal_syment *is;
-
- /* Relocations against a TC0 TOC anchor are
- automatically transformed to be against
- the TOC anchor in the output file. */
- is = finfo->internal_syms + r_symndx;
- if (is->n_sclass == C_HIDEXT
- && is->n_numaux > 0)
- {
- PTR auxptr;
- union internal_auxent aux;
-
- auxptr = ((PTR)
- (((bfd_byte *)
- obj_coff_external_syms (input_bfd))
- + ((r_symndx + is->n_numaux)
- * isymesz)));
- bfd_coff_swap_aux_in (input_bfd, auxptr,
- is->n_type, is->n_sclass,
- is->n_numaux - 1,
- is->n_numaux,
- (PTR) &aux);
- if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
- && aux.x_csect.x_smclas == XMC_TC0)
- indx = finfo->toc_symindx;
- }
- }
+ if (indx != -1)
+ irel->r_symndx = indx;
+ else
+ {
- if (indx != -1)
- irel->r_symndx = indx;
- else
- {
- struct internal_syment *is;
- const char *name;
- char buf[SYMNMLEN + 1];
-
- /* This reloc is against a symbol we are
- stripping. It would be possible to handle
- this case, but I don't think it's worth it. */
- is = finfo->internal_syms + r_symndx;
-
- name = (_bfd_coff_internal_syment_name
- (input_bfd, is, buf));
- if (name == NULL)
- return false;
+ struct internal_syment *is;
- if (! ((*finfo->info->callbacks->unattached_reloc)
- (finfo->info, name, input_bfd, o,
- irel->r_vaddr)))
- return false;
- }
- }
- }
+ const char *name;
+ char buf[SYMNMLEN + 1];
- quiet = false;
- switch (irel->r_type)
- {
- default:
- if (h == NULL
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak
- || h->root.type == bfd_link_hash_common)
- break;
- /* Fall through. */
- case R_POS:
- case R_NEG:
- case R_RL:
- case R_RLA:
- /* This reloc needs to be copied into the .loader
- section. */
- ldrel.l_vaddr = irel->r_vaddr;
- if (r_symndx == -1)
- ldrel.l_symndx = -1;
- else if (h == NULL
- || (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak
- || h->root.type == bfd_link_hash_common))
- {
- asection *sec;
+ /* This reloc is against a symbol we are
+ stripping. It would be possible to handle
+ this case, but I don't think it's worth it. */
+ is = finfo->internal_syms + r_symndx;
- if (h == NULL)
- sec = xcoff_data (input_bfd)->csects[r_symndx];
- else if (h->root.type == bfd_link_hash_common)
- sec = h->root.u.c.p->section;
- else
- sec = h->root.u.def.section;
- sec = sec->output_section;
-
- if (strcmp (sec->name, ".text") == 0)
- ldrel.l_symndx = 0;
- else if (strcmp (sec->name, ".data") == 0)
- ldrel.l_symndx = 1;
- else if (strcmp (sec->name, ".bss") == 0)
- ldrel.l_symndx = 2;
- else
- {
- (*_bfd_error_handler)
- (_("%s: loader reloc in unrecognized section `%s'"),
- bfd_get_filename (input_bfd),
- sec->name);
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
- }
- else
- {
- if (! finfo->info->relocateable
- && (h->flags & XCOFF_DEF_DYNAMIC) == 0
- && (h->flags & XCOFF_IMPORT) == 0)
- {
- /* We already called the undefined_symbol
- callback for this relocation, in
- _bfd_ppc_xcoff_relocate_section. Don't
- issue any more warnings. */
- quiet = true;
- }
- if (h->ldindx < 0 && ! quiet)
- {
- (*_bfd_error_handler)
- (_("%s: `%s' in loader reloc but not loader sym"),
- bfd_get_filename (input_bfd),
- h->root.root.string);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- ldrel.l_symndx = h->ldindx;
- }
- ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
- ldrel.l_rsecnm = o->output_section->target_index;
- if (xcoff_hash_table (finfo->info)->textro
- && strcmp (o->output_section->name, ".text") == 0
- && ! quiet)
- {
- (*_bfd_error_handler)
- (_("%s: loader reloc in read-only section %s"),
- bfd_get_filename (input_bfd),
- bfd_get_section_name (finfo->output_bfd,
- o->output_section));
- bfd_set_error (bfd_error_invalid_operation);
+ name = (_bfd_coff_internal_syment_name
+ (input_bfd, is, buf));
+
+ if (name == NULL)
return false;
- }
- xcoff_swap_ldrel_out (output_bfd, &ldrel,
- finfo->ldrel);
- BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
- ++finfo->ldrel;
- break;
- case R_TOC:
- case R_GL:
- case R_TCL:
- case R_TRL:
- case R_TRLA:
- /* We should never need a .loader reloc for a TOC
- relative reloc. */
- break;
- }
- }
+ if (! ((*finfo->info->callbacks->unattached_reloc)
+ (finfo->info, name, input_bfd, o,
+ irel->r_vaddr)))
+ return false;
+ }
+ }
+ }
- o->output_section->reloc_count += o->reloc_count;
- }
+ quiet = false;
+ switch (irel->r_type)
+ {
+ default:
+ if (h == NULL
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common)
+ break;
+ /* Fall through. */
+ case R_POS:
+ case R_NEG:
+ case R_RL:
+ case R_RLA:
+ /* This reloc needs to be copied into the .loader
+ section. */
+ ldrel.l_vaddr = irel->r_vaddr;
+ if (r_symndx == -1)
+ ldrel.l_symndx = -1;
+ else if (h == NULL
+ || (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common))
+ {
+ asection *sec;
+
+ if (h == NULL)
+ sec = xcoff_data (input_bfd)->csects[r_symndx];
+ else if (h->root.type == bfd_link_hash_common)
+ sec = h->root.u.c.p->section;
+ else
+ sec = h->root.u.def.section;
+ sec = sec->output_section;
+
+ if (strcmp (sec->name, ".text") == 0)
+ ldrel.l_symndx = 0;
+ else if (strcmp (sec->name, ".data") == 0)
+ ldrel.l_symndx = 1;
+ else if (strcmp (sec->name, ".bss") == 0)
+ ldrel.l_symndx = 2;
+ else
+ {
+ (*_bfd_error_handler)
+ (_("%s: loader reloc in unrecognized section `%s'"),
+ bfd_get_filename (input_bfd),
+ sec->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ }
+ else
+ {
+ if (! finfo->info->relocateable
+ && (h->flags & XCOFF_DEF_DYNAMIC) == 0
+ && (h->flags & XCOFF_IMPORT) == 0)
+ {
+ /* We already called the undefined_symbol
+ callback for this relocation, in
+ _bfd_ppc_xcoff_relocate_section. Don't
+ issue any more warnings. */
+ quiet = true;
+ }
+ if (h->ldindx < 0 && ! quiet)
+ {
+ (*_bfd_error_handler)
+ (_("%s: `%s' in loader reloc but not loader sym"),
+ bfd_get_filename (input_bfd),
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ ldrel.l_symndx = h->ldindx;
+ }
+ ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
+ ldrel.l_rsecnm = o->output_section->target_index;
+ if (xcoff_hash_table (finfo->info)->textro
+ && strcmp (o->output_section->name, ".text") == 0
+ && ! quiet)
+ {
+ (*_bfd_error_handler)
+ (_("%s: loader reloc in read-only section %s"),
+ bfd_get_filename (input_bfd),
+ bfd_get_section_name (finfo->output_bfd,
+ o->output_section));
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel,
+ finfo->ldrel);
- /* Write out the modified section contents. */
- if (! bfd_set_section_contents (output_bfd, o->output_section,
- contents, o->output_offset,
- (o->_cooked_size != 0
- ? o->_cooked_size
- : o->_raw_size)))
- return false;
+ finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
+ break;
+
+ case R_TOC:
+ case R_GL:
+ case R_TCL:
+ case R_TRL:
+ case R_TRLA:
+ /* We should never need a .loader reloc for a TOC
+ relative reloc. */
+ break;
+ }
+ }
+
+ o->output_section->reloc_count += o->reloc_count;
}
+ /* Write out the modified section contents. */
+ if (! bfd_set_section_contents (output_bfd, o->output_section,
+ contents, o->output_offset,
+ (o->_cooked_size != 0
+ ? o->_cooked_size
+ : o->_raw_size)))
+ return false;
+ }
+
obj_coff_keep_syms (input_bfd) = keep_syms;
if (! finfo->info->keep_memory)
@@ -5610,6 +5278,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
/* Write out a non-XCOFF global symbol. */
+
static boolean
xcoff_write_global_symbol (h, p)
struct xcoff_link_hash_entry *h;
@@ -5620,6 +5289,7 @@ xcoff_write_global_symbol (h, p)
bfd_byte *outsym;
struct internal_syment isym;
union internal_auxent aux;
+ boolean result;
output_bfd = finfo->output_bfd;
outsym = finfo->outsyms;
@@ -5630,97 +5300,123 @@ xcoff_write_global_symbol (h, p)
return true;
/* If we need a .loader section entry, write it out. */
- if (h->ldsym != NULL)
- {
- struct internal_ldsym *ldsym;
- bfd *impbfd;
+ if (h->ldsym != NULL) {
+ struct internal_ldsym *ldsym;
+ bfd *impbfd;
+
+ ldsym = h->ldsym;
- ldsym = h->ldsym;
+ if (h->root.type == bfd_link_hash_undefined ||
+ h->root.type == bfd_link_hash_undefweak) {
- if (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- {
- ldsym->l_value = 0;
- ldsym->l_scnum = N_UNDEF;
- ldsym->l_smtype = XTY_ER;
- impbfd = h->root.u.undef.abfd;
- }
- else if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *sec;
+ ldsym->l_value = 0;
+ ldsym->l_scnum = N_UNDEF;
+ ldsym->l_smtype = XTY_ER;
+ impbfd = h->root.u.undef.abfd;
- sec = h->root.u.def.section;
- ldsym->l_value = (sec->output_section->vma
- + sec->output_offset
- + h->root.u.def.value);
- ldsym->l_scnum = sec->output_section->target_index;
- ldsym->l_smtype = XTY_SD;
- impbfd = sec->owner;
- }
- else
- abort ();
+ } else if (h->root.type == bfd_link_hash_defined ||
+ h->root.type == bfd_link_hash_defweak) {
- if (((h->flags & XCOFF_DEF_REGULAR) == 0
- && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
- || (h->flags & XCOFF_IMPORT) != 0)
- ldsym->l_smtype |= L_IMPORT;
- if (((h->flags & XCOFF_DEF_REGULAR) != 0
- && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
- || (h->flags & XCOFF_EXPORT) != 0)
- ldsym->l_smtype |= L_EXPORT;
- if ((h->flags & XCOFF_ENTRY) != 0)
- ldsym->l_smtype |= L_ENTRY;
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ ldsym->l_value = (sec->output_section->vma
+ + sec->output_offset
+ + h->root.u.def.value);
+ ldsym->l_scnum = sec->output_section->target_index;
+ ldsym->l_smtype = XTY_SD;
+ impbfd = sec->owner;
+
+ } else {
+ abort ();
+ }
- ldsym->l_smclas = h->smclas;
+ if (((h->flags & XCOFF_DEF_REGULAR) == 0 &&
+ (h->flags & XCOFF_DEF_DYNAMIC) != 0) ||
+ (h->flags & XCOFF_IMPORT) != 0) {
+ ldsym->l_smtype |= L_IMPORT;
+ }
- if (ldsym->l_ifile == (bfd_size_type) -1)
- ldsym->l_ifile = 0;
- else if (ldsym->l_ifile == 0)
- {
- if ((ldsym->l_smtype & L_IMPORT) == 0)
- ldsym->l_ifile = 0;
- else if (impbfd == NULL)
- ldsym->l_ifile = 0;
- else
- {
- BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
- ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
- }
- }
+ if (((h->flags & XCOFF_DEF_REGULAR) != 0 &&
+ (h->flags & XCOFF_DEF_DYNAMIC) != 0) ||
+ (h->flags & XCOFF_EXPORT) != 0) {
+ ldsym->l_smtype |= L_EXPORT;
+ }
- ldsym->l_parm = 0;
+ if ((h->flags & XCOFF_ENTRY) != 0) {
+ ldsym->l_smtype |= L_ENTRY;
+ }
- BFD_ASSERT (h->ldindx >= 0);
- BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
- xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + h->ldindx - 3);
- h->ldsym = NULL;
+ if ((h->flags & XCOFF_RTINIT) != 0) {
+ ldsym->l_smtype = XTY_SD;
}
+ ldsym->l_smclas = h->smclas;
+
+ if (ldsym->l_ifile == (bfd_size_type) -1) {
+ ldsym->l_ifile = 0;
+
+ } else if (ldsym->l_ifile == 0) {
+ if ((ldsym->l_smtype & L_IMPORT) == 0) {
+ ldsym->l_ifile = 0;
+ } else if (impbfd == NULL) {
+ ldsym->l_ifile = 0;
+ } else {
+ BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
+ ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
+ }
+ }
+
+ ldsym->l_parm = 0;
+
+ BFD_ASSERT (h->ldindx >= 0);
+
+ bfd_xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym +
+ (h->ldindx - 3) *
+ bfd_xcoff_ldsymsz(finfo->output_bfd));
+ h->ldsym = NULL;
+ }
+
/* If this symbol needs global linkage code, write it out. */
- if (h->root.type == bfd_link_hash_defined
- && (h->root.u.def.section
- == xcoff_hash_table (finfo->info)->linkage_section))
- {
- bfd_byte *p;
- bfd_vma tocoff;
- unsigned int i;
-
- p = h->root.u.def.section->contents + h->root.u.def.value;
-
- /* The first instruction in the global linkage code loads a
- specific TOC element. */
- tocoff = (h->descriptor->toc_section->output_section->vma
- + h->descriptor->toc_section->output_offset
- - xcoff_data (output_bfd)->toc);
- if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
- tocoff += h->descriptor->u.toc_offset;
- bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
- for (i = 0, p += 4;
- i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
- i++, p += 4)
- bfd_put_32 (output_bfd, xcoff_glink_code[i], p);
+ if (h->root.type == bfd_link_hash_defined &&
+ (h->root.u.def.section ==
+ xcoff_hash_table (finfo->info)->linkage_section)) {
+
+ bfd_byte *p;
+ bfd_vma tocoff;
+ unsigned int i;
+
+ p = h->root.u.def.section->contents + h->root.u.def.value;
+
+ /* The first instruction in the global linkage code loads a
+ specific TOC element. */
+ tocoff = (h->descriptor->toc_section->output_section->vma
+ + h->descriptor->toc_section->output_offset
+ - xcoff_data (output_bfd)->toc);
+
+ if ((h->descriptor->flags & XCOFF_SET_TOC) != 0) {
+ tocoff += h->descriptor->u.toc_offset;
}
+
+
+ /*
+ * The first instruction in the glink code needs to be cooked to
+ * to hold the correct offset in the toc. The rest are just outputted
+ * raw.
+ */
+ bfd_put_32 (output_bfd,
+ bfd_xcoff_glink_code(output_bfd, 0) | (tocoff & 0xffff), p);
+
+ /*
+ * Start with i == 1 to get past the first instruction done above
+ * The /4 is because the glink code is in bytes and we are going 4
+ * at a pop
+ */
+ for (i = 1; i < bfd_xcoff_glink_code_size(output_bfd) / 4; i++) {
+ bfd_put_32 (output_bfd, bfd_xcoff_glink_code(output_bfd, i),
+ &p[4 * i]);
+ }
+ }
/* If we created a TOC entry for this symbol, write out the required
relocs. */
@@ -5741,69 +5437,82 @@ xcoff_write_global_symbol (h, p)
irel->r_vaddr = (osec->vma
+ tocsec->output_offset
+ h->u.toc_offset);
- if (h->indx >= 0)
+
+
+ if (h->indx >= 0) {
irel->r_symndx = h->indx;
- else
- {
- h->indx = -2;
- irel->r_symndx = obj_raw_syment_count (output_bfd);
- }
+ } else {
+ h->indx = -2;
+ irel->r_symndx = obj_raw_syment_count (output_bfd);
+ }
+
+ BFD_ASSERT (h->ldindx >= 0);
+
+ /*
+ * Initialize the aux union here instead of closer to when it is
+ * written out below because the length of the csect depends on
+ * whether the output is 32 or 64 bit
+ */
+ memset (&iraux, 0, sizeof iraux);
+ iraux.x_csect.x_smtyp = XTY_SD;
+ /* iraux.x_csect.x_scnlen.l = 4 or 8, see below */
+ iraux.x_csect.x_smclas = XMC_TC;
+
+
+ /*
+ * 32 bit uses a 32 bit R_POS to do the relocations
+ * 64 bit uses a 64 bit R_POS to do the relocations
+ *
+ * Also needs to change the csect size : 4 for 32 bit, 8 for 64 bit
+ *
+ * Which one is determined by the backend
+ */
+ if (bfd_xcoff_is_xcoff64(output_bfd)) {
+ irel->r_size = 63;
+ iraux.x_csect.x_scnlen.l = 8;
+ } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
+ irel->r_size = 31;
+ iraux.x_csect.x_scnlen.l = 4;
+ } else {
+ return false;
+ }
irel->r_type = R_POS;
- irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
- BFD_ASSERT (h->ldindx >= 0);
ldrel.l_vaddr = irel->r_vaddr;
ldrel.l_symndx = h->ldindx;
- ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rtype = (irel->r_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
- xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
- ++finfo->ldrel;
+ bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
- /* We need to emit a symbol to define a csect which holds the
- reloc. */
- if (finfo->info->strip != strip_all)
- {
- if (strlen (h->root.root.string) <= SYMNMLEN)
- strncpy (irsym._n._n_name, h->root.root.string, SYMNMLEN);
- else
- {
- boolean hash;
- bfd_size_type indx;
+ /* We need to emit a symbol to define a csect which holds the reloc. */
+ if (finfo->info->strip != strip_all) {
- hash = true;
- if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
- hash = false;
- indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string,
- hash, false);
- if (indx == (bfd_size_type) -1)
- return false;
- irsym._n._n_n._n_zeroes = 0;
- irsym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
- }
-
- irsym.n_value = irel->r_vaddr;
- irsym.n_scnum = osec->target_index;
- irsym.n_sclass = C_HIDEXT;
- irsym.n_type = T_NULL;
- irsym.n_numaux = 1;
+ result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &irsym,
+ h->root.root.string);
+ if (false == result) {
+ return false;
+ }
- bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
- outsym += bfd_coff_symesz (output_bfd);
+ irsym.n_value = irel->r_vaddr;
+ irsym.n_scnum = osec->target_index;
+ irsym.n_sclass = C_HIDEXT;
+ irsym.n_type = T_NULL;
+ irsym.n_numaux = 1;
- memset (&iraux, 0, sizeof iraux);
- iraux.x_csect.x_smtyp = XTY_SD;
- iraux.x_csect.x_scnlen.l = 4;
- iraux.x_csect.x_smclas = XMC_TC;
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
+ outsym += bfd_coff_symesz (output_bfd);
- bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT,
- 0, 1, (PTR) outsym);
- outsym += bfd_coff_auxesz (output_bfd);
+ /* note : iraux is initialized above */
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT,
+ 0, 1, (PTR) outsym);
+ outsym += bfd_coff_auxesz (output_bfd);
- if (h->indx >= 0)
- {
- /* We aren't going to write out the symbols below, so we
+ if (h->indx >= 0)
+ {
+ /* We aren't going to write out the symbols below, so we
need to write them out now. */
if (bfd_seek (output_bfd,
(obj_sym_filepos (output_bfd)
@@ -5822,10 +5531,18 @@ xcoff_write_global_symbol (h, p)
}
}
- /* If this symbol is a specially defined function descriptor, write
- it out. The first word is the address of the function code
- itself, the second word is the address of the TOC, and the third
- word is zero. */
+ /*
+ * If this symbol is a specially defined function descriptor, write
+ * it out. The first word is the address of the function code
+ * itself, the second word is the address of the TOC, and the third
+ * word is zero.
+ *
+ * 32 bit vs 64 bit
+ * The addresses for the 32 bit will take 4 bytes and the addresses
+ * for 64 bit will take 8 bytes. Similar for the relocs. This type
+ * of logic was also done above to create a TOC entry in
+ * xcoff_write_global_symbol
+ */
if ((h->flags & XCOFF_DESCRIPTOR) != 0
&& h->root.type == bfd_link_hash_defined
&& (h->root.u.def.section
@@ -5840,6 +5557,17 @@ xcoff_write_global_symbol (h, p)
struct internal_reloc *irel;
struct internal_ldrel ldrel;
asection *tsec;
+ unsigned int reloc_size, byte_size;
+
+ if (bfd_xcoff_is_xcoff64(output_bfd)) {
+ reloc_size = 63;
+ byte_size = 8;
+ } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
+ reloc_size = 31;
+ byte_size = 4;
+ } else {
+ return false;
+ }
sec = h->root.u.def.section;
osec = sec->output_section;
@@ -5851,11 +5579,6 @@ xcoff_write_global_symbol (h, p)
&& (hentry->root.type == bfd_link_hash_defined
|| hentry->root.type == bfd_link_hash_defweak));
esec = hentry->root.u.def.section;
- bfd_put_32 (output_bfd,
- (esec->output_section->vma
- + esec->output_offset
- + hentry->root.u.def.value),
- p);
irel = finfo->section_info[oindx].relocs + osec->reloc_count;
irel->r_vaddr = (osec->vma
@@ -5863,7 +5586,7 @@ xcoff_write_global_symbol (h, p)
+ h->root.u.def.value);
irel->r_symndx = esec->output_section->target_index;
irel->r_type = R_POS;
- irel->r_size = 31;
+ irel->r_size = reloc_size;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
@@ -5883,13 +5606,38 @@ xcoff_write_global_symbol (h, p)
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
- ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rtype = (reloc_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
- xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
- ++finfo->ldrel;
-
- bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
-
+ bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
+
+ /*
+ * There are three items to write out,
+ * the address of the code
+ * the address of the toc anchor
+ * the environment pointer.
+ * We are ignoring the environment pointer. So set it to zero
+ */
+ if (bfd_xcoff_is_xcoff64(output_bfd)) {
+ bfd_put_64 (output_bfd, (esec->output_section->vma +
+ esec->output_offset +
+ hentry->root.u.def.value), p);
+ bfd_put_64 (output_bfd, xcoff_data (output_bfd)->toc, p + 8);
+ bfd_put_64 (output_bfd, 0, p + 16);
+ } else {
+ /*
+ * 32 bit backend
+ *
+ * This logic was already called above so the error case where
+ * the backend is neither has already been checked
+ */
+ bfd_put_32 (output_bfd, (esec->output_section->vma +
+ esec->output_offset +
+ hentry->root.u.def.value), p);
+ bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
+ bfd_put_32 (output_bfd, 0, p + 8);
+ }
+
tsec = coff_section_from_bfd_index (output_bfd,
xcoff_data (output_bfd)->sntoc);
@@ -5897,10 +5645,10 @@ xcoff_write_global_symbol (h, p)
irel->r_vaddr = (osec->vma
+ sec->output_offset
+ h->root.u.def.value
- + 4);
+ + byte_size);
irel->r_symndx = tsec->output_section->target_index;
irel->r_type = R_POS;
- irel->r_size = 31;
+ irel->r_size = reloc_size;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
@@ -5920,10 +5668,10 @@ xcoff_write_global_symbol (h, p)
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
- ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rtype = (reloc_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
- xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
- ++finfo->ldrel;
+ bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
}
if (h->indx >= 0 || finfo->info->strip == strip_all)
@@ -5954,23 +5702,11 @@ xcoff_write_global_symbol (h, p)
h->indx = obj_raw_syment_count (output_bfd);
- if (strlen (h->root.root.string) <= SYMNMLEN)
- strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
- else
- {
- boolean hash;
- bfd_size_type indx;
-
- hash = true;
- if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
- hash = false;
- indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
- false);
- if (indx == (bfd_size_type) -1)
- return false;
- isym._n._n_n._n_zeroes = 0;
- isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
- }
+ result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &isym,
+ h->root.root.string);
+ if (false == result) {
+ return false;
+ }
if (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
@@ -6035,7 +5771,6 @@ xcoff_write_global_symbol (h, p)
outsym += bfd_coff_symesz (output_bfd);
aux.x_csect.x_smclas = h->smclas;
-
bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, isym.n_sclass, 0, 1,
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
@@ -6054,7 +5789,6 @@ xcoff_write_global_symbol (h, p)
aux.x_csect.x_smtyp = XTY_LD;
aux.x_csect.x_scnlen.l = obj_raw_syment_count (output_bfd);
-
bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, C_EXT, 0, 1,
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
@@ -6253,8 +5987,8 @@ xcoff_reloc_link_order (output_bfd, finfo, output_section, link_order)
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
ldrel.l_rsecnm = output_section->target_index;
- xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
- ++finfo->ldrel;
+ bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
return true;
}
@@ -6277,355 +6011,6 @@ xcoff_sort_relocs (p1, p2)
return 0;
}
-/* This is the relocation function for the RS/6000/POWER/PowerPC.
- This is currently the only processor which uses XCOFF; I hope that
- will never change. */
-
-boolean
-_bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
- input_section, contents, relocs, syms,
- sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- struct internal_reloc *relocs;
- struct internal_syment *syms;
- asection **sections;
-{
- struct internal_reloc *rel;
- struct internal_reloc *relend;
-
- rel = relocs;
- relend = rel + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- long symndx;
- struct xcoff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma addend;
- bfd_vma val;
- struct reloc_howto_struct howto;
- bfd_reloc_status_type rstat;
-
- /* Relocation type R_REF is a special relocation type which is
- merely used to prevent garbage collection from occurring for
- the csect including the symbol which it references. */
- if (rel->r_type == R_REF)
- continue;
-
- symndx = rel->r_symndx;
-
- if (symndx == -1)
- {
- h = NULL;
- sym = NULL;
- addend = 0;
- }
- else
- {
- h = obj_xcoff_sym_hashes (input_bfd)[symndx];
- sym = syms + symndx;
- addend = - sym->n_value;
- }
-
- /* We build the howto information on the fly. */
-
- howto.type = rel->r_type;
- howto.rightshift = 0;
- howto.size = 2;
- howto.bitsize = (rel->r_size & 0x1f) + 1;
- howto.pc_relative = false;
- howto.bitpos = 0;
- if ((rel->r_size & 0x80) != 0)
- howto.complain_on_overflow = complain_overflow_signed;
- else
- howto.complain_on_overflow = complain_overflow_bitfield;
- howto.special_function = NULL;
- howto.name = "internal";
- howto.partial_inplace = true;
- if (howto.bitsize == 32)
- howto.src_mask = howto.dst_mask = 0xffffffff;
- else
- {
- howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
- if (howto.bitsize == 16)
- howto.size = 1;
- }
- howto.pcrel_offset = false;
-
- val = 0;
-
- if (h == NULL)
- {
- asection *sec;
-
- if (symndx == -1)
- {
- sec = bfd_abs_section_ptr;
- val = 0;
- }
- else
- {
- sec = sections[symndx];
- /* Hack to make sure we use the right TOC anchor value
- if this reloc is against the TOC anchor. */
- if (sec->name[3] == '0'
- && strcmp (sec->name, ".tc0") == 0)
- val = xcoff_data (output_bfd)->toc;
- else
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value
- - sec->vma);
- }
- }
- else
- {
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *sec;
-
- sec = h->root.u.def.section;
- val = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else if (h->root.type == bfd_link_hash_common)
- {
- asection *sec;
- sec = h->root.u.c.p->section;
- val = (sec->output_section->vma
- + sec->output_offset);
- }
- else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
- || (h->flags & XCOFF_IMPORT) != 0)
- {
- /* Every symbol in a shared object is defined somewhere. */
- val = 0;
- }
- else if (! info->relocateable)
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma, true)))
- return false;
-
- /* Don't try to process the reloc. It can't help, and
- it may generate another error. */
- continue;
- }
- }
- /* I took the relocation type definitions from two documents:
- the PowerPC AIX Version 4 Application Binary Interface, First
- Edition (April 1992), and the PowerOpen ABI, Big-Endian
- 32-Bit Hardware Implementation (June 30, 1994). Differences
- between the documents are noted below. */
- switch (rel->r_type)
- {
- case R_RTB:
- case R_RRTBI:
- case R_RRTBA:
- /* These relocs are defined by the PowerPC ABI to be
- relative branches which use half of the difference
- between the symbol and the program counter. I can't
- quite figure out when this is useful. These relocs are
- not defined by the PowerOpen ABI. */
- default:
- (*_bfd_error_handler)
- (_("%s: unsupported relocation type 0x%02x"),
- bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
- bfd_set_error (bfd_error_bad_value);
- return false;
- case R_POS:
- /* Simple positive relocation. */
- break;
- case R_NEG:
- /* Simple negative relocation. */
- val = - val;
- break;
- case R_REL:
- /* Simple PC relative relocation. */
- howto.pc_relative = true;
- break;
- case R_TOC:
- /* TOC relative relocation. The value in the instruction in
- the input file is the offset from the input file TOC to
- the desired location. We want the offset from the final
- TOC to the desired location. We have:
- isym = iTOC + in
- iinsn = in + o
- osym = oTOC + on
- oinsn = on + o
- so we must change insn by on - in.
- */
- case R_GL:
- /* Global linkage relocation. The value of this relocation
- is the address of the entry in the TOC section. */
- case R_TCL:
- /* Local object TOC address. I can't figure out the
- difference between this and case R_GL. */
- case R_TRL:
- /* TOC relative relocation. A TOC relative load instruction
- which may be changed to a load address instruction.
- FIXME: We don't currently implement this optimization. */
- case R_TRLA:
- /* TOC relative relocation. This is a TOC relative load
- address instruction which may be changed to a load
- instruction. FIXME: I don't know if this is the correct
- implementation. */
- if (h != NULL && h->smclas != XMC_TD)
- {
- if (h->toc_section == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
- bfd_get_filename (input_bfd), rel->r_vaddr,
- h->root.root.string);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
- val = (h->toc_section->output_section->vma
- + h->toc_section->output_offset);
- }
-
- val = ((val - xcoff_data (output_bfd)->toc)
- - (sym->n_value - xcoff_data (input_bfd)->toc));
- addend = 0;
- break;
- case R_BA:
- /* Absolute branch. We don't want to mess with the lower
- two bits of the instruction. */
- case R_CAI:
- /* The PowerPC ABI defines this as an absolute call which
- may be modified to become a relative call. The PowerOpen
- ABI does not define this relocation type. */
- case R_RBA:
- /* Absolute branch which may be modified to become a
- relative branch. */
- case R_RBAC:
- /* The PowerPC ABI defines this as an absolute branch to a
- fixed address which may be modified to an absolute branch
- to a symbol. The PowerOpen ABI does not define this
- relocation type. */
- case R_RBRC:
- /* The PowerPC ABI defines this as an absolute branch to a
- fixed address which may be modified to a relative branch.
- The PowerOpen ABI does not define this relocation type. */
- howto.src_mask &= ~3;
- howto.dst_mask = howto.src_mask;
- break;
- case R_BR:
- /* Relative branch. We don't want to mess with the lower
- two bits of the instruction. */
- case R_CREL:
- /* The PowerPC ABI defines this as a relative call which may
- be modified to become an absolute call. The PowerOpen
- ABI does not define this relocation type. */
- case R_RBR:
- /* A relative branch which may be modified to become an
- absolute branch. FIXME: We don't implement this,
- although we should for symbols of storage mapping class
- XMC_XO. */
- howto.pc_relative = true;
- howto.src_mask &= ~3;
- howto.dst_mask = howto.src_mask;
- break;
- case R_RL:
- /* The PowerPC AIX ABI describes this as a load which may be
- changed to a load address. The PowerOpen ABI says this
- is the same as case R_POS. */
- break;
- case R_RLA:
- /* The PowerPC AIX ABI describes this as a load address
- which may be changed to a load. The PowerOpen ABI says
- this is the same as R_POS. */
- break;
- }
-
- /* If we see an R_BR or R_RBR reloc which is jumping to global
- linkage code, and it is followed by an appropriate cror nop
- instruction, we replace the cror with lwz r2,20(r1). This
- restores the TOC after the glink code. Contrariwise, if the
- call is followed by a lwz r2,20(r1), but the call is not
- going to global linkage code, we can replace the load with a
- cror. */
- if ((rel->r_type == R_BR || rel->r_type == R_RBR)
- && h != NULL
- && h->root.type == bfd_link_hash_defined
- && (rel->r_vaddr - input_section->vma + 8
- <= input_section->_cooked_size))
- {
- bfd_byte *pnext;
- unsigned long next;
-
- pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
- next = bfd_get_32 (input_bfd, pnext);
-
- /* The _ptrgl function is magic. It is used by the AIX
- compiler to call a function through a pointer. */
- if (h->smclas == XMC_GL
- || strcmp (h->root.root.string, "._ptrgl") == 0)
- {
- if (next == 0x4def7b82 /* cror 15,15,15 */
- || next == 0x4ffffb82 /* cror 31,31,31 */
- || next == 0x60000000) /* ori r0,r0,0 */
- bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */
- }
- else
- {
- if (next == 0x80410014) /* lwz r1,20(r1) */
- bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
- }
- }
-
- /* A PC relative reloc includes the section address. */
- if (howto.pc_relative)
- addend += input_section->vma;
-
- rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
- contents,
- rel->r_vaddr - input_section->vma,
- val, addend);
-
- switch (rstat)
- {
- default:
- abort ();
- case bfd_reloc_ok:
- break;
- case bfd_reloc_overflow:
- {
- const char *name;
- char buf[SYMNMLEN + 1];
- char howto_name[10];
-
- if (symndx == -1)
- name = "*ABS*";
- else if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
- if (name == NULL)
- return false;
- }
- sprintf (howto_name, "0x%02x", rel->r_type);
-
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto_name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_vaddr - input_section->vma)))
- return false;
- }
- }
- }
-
- return true;
-}