xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/coff-rs6000.c (revision d04417c8bbac460f44f2231b23295dffb631d02d)
13d8817e4Smiod /* BFD back-end for IBM RS/6000 "XCOFF" files.
23d8817e4Smiod    Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
33d8817e4Smiod    Free Software Foundation, Inc.
43d8817e4Smiod    FIXME: Can someone provide a transliteration of this name into ASCII?
53d8817e4Smiod    Using the following chars caused a compiler warning on HIUX (so I replaced
63d8817e4Smiod    them with octal escapes), and isn't useful without an understanding of what
73d8817e4Smiod    character set it is.
83d8817e4Smiod    Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
93d8817e4Smiod      and John Gilmore.
103d8817e4Smiod    Archive support from Damon A. Permezel.
113d8817e4Smiod    Contributed by IBM Corporation and Cygnus Support.
123d8817e4Smiod 
133d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
143d8817e4Smiod 
153d8817e4Smiod This program is free software; you can redistribute it and/or modify
163d8817e4Smiod it under the terms of the GNU General Public License as published by
173d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
183d8817e4Smiod (at your option) any later version.
193d8817e4Smiod 
203d8817e4Smiod This program is distributed in the hope that it will be useful,
213d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
223d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
233d8817e4Smiod GNU General Public License for more details.
243d8817e4Smiod 
253d8817e4Smiod You should have received a copy of the GNU General Public License
263d8817e4Smiod along with this program; if not, write to the Free Software
273d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
283d8817e4Smiod 
293d8817e4Smiod #include "bfd.h"
303d8817e4Smiod #include "sysdep.h"
313d8817e4Smiod #include "bfdlink.h"
323d8817e4Smiod #include "libbfd.h"
333d8817e4Smiod #include "coff/internal.h"
343d8817e4Smiod #include "coff/xcoff.h"
353d8817e4Smiod #include "coff/rs6000.h"
363d8817e4Smiod #include "libcoff.h"
373d8817e4Smiod #include "libxcoff.h"
383d8817e4Smiod 
393d8817e4Smiod extern bfd_boolean _bfd_xcoff_mkobject
403d8817e4Smiod   PARAMS ((bfd *));
413d8817e4Smiod extern bfd_boolean _bfd_xcoff_copy_private_bfd_data
423d8817e4Smiod   PARAMS ((bfd *, bfd *));
433d8817e4Smiod extern bfd_boolean _bfd_xcoff_is_local_label_name
443d8817e4Smiod   PARAMS ((bfd *, const char *));
453d8817e4Smiod extern reloc_howto_type *_bfd_xcoff_reloc_type_lookup
463d8817e4Smiod   PARAMS ((bfd *, bfd_reloc_code_real_type));
473d8817e4Smiod extern bfd_boolean _bfd_xcoff_slurp_armap
483d8817e4Smiod   PARAMS ((bfd *));
493d8817e4Smiod extern const bfd_target *_bfd_xcoff_archive_p
503d8817e4Smiod   PARAMS ((bfd *));
513d8817e4Smiod extern PTR _bfd_xcoff_read_ar_hdr
523d8817e4Smiod   PARAMS ((bfd *));
533d8817e4Smiod extern bfd *_bfd_xcoff_openr_next_archived_file
543d8817e4Smiod   PARAMS ((bfd *, bfd *));
553d8817e4Smiod extern int _bfd_xcoff_stat_arch_elt
563d8817e4Smiod   PARAMS ((bfd *, struct stat *));
573d8817e4Smiod extern bfd_boolean _bfd_xcoff_write_armap
583d8817e4Smiod   PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
593d8817e4Smiod extern bfd_boolean _bfd_xcoff_write_archive_contents
603d8817e4Smiod   PARAMS ((bfd *));
613d8817e4Smiod extern int _bfd_xcoff_sizeof_headers
623d8817e4Smiod   PARAMS ((bfd *, bfd_boolean));
633d8817e4Smiod extern void _bfd_xcoff_swap_sym_in
643d8817e4Smiod   PARAMS ((bfd *, PTR, PTR));
653d8817e4Smiod extern unsigned int _bfd_xcoff_swap_sym_out
663d8817e4Smiod   PARAMS ((bfd *, PTR, PTR));
673d8817e4Smiod extern void _bfd_xcoff_swap_aux_in
683d8817e4Smiod   PARAMS ((bfd *, PTR, int, int, int, int, PTR));
693d8817e4Smiod extern unsigned int _bfd_xcoff_swap_aux_out
703d8817e4Smiod   PARAMS ((bfd *, PTR, int, int, int, int, PTR));
713d8817e4Smiod static void xcoff_swap_reloc_in
723d8817e4Smiod   PARAMS ((bfd *, PTR, PTR));
733d8817e4Smiod static unsigned int xcoff_swap_reloc_out
743d8817e4Smiod   PARAMS ((bfd *, PTR, PTR));
753d8817e4Smiod 
763d8817e4Smiod /* Forward declare xcoff_rtype2howto for coffcode.h macro.  */
773d8817e4Smiod void xcoff_rtype2howto
783d8817e4Smiod   PARAMS ((arelent *, struct internal_reloc *));
793d8817e4Smiod 
803d8817e4Smiod /* coffcode.h needs these to be defined.  */
813d8817e4Smiod #define RS6000COFF_C 1
823d8817e4Smiod 
833d8817e4Smiod #define SELECT_RELOC(internal, howto)					\
843d8817e4Smiod   {									\
853d8817e4Smiod     internal.r_type = howto->type;					\
863d8817e4Smiod     internal.r_size =							\
873d8817e4Smiod       ((howto->complain_on_overflow == complain_overflow_signed		\
883d8817e4Smiod 	? 0x80								\
893d8817e4Smiod 	: 0)								\
903d8817e4Smiod        | (howto->bitsize - 1));						\
913d8817e4Smiod   }
923d8817e4Smiod 
933d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
943d8817e4Smiod #define COFF_LONG_FILENAMES
953d8817e4Smiod #define NO_COFF_SYMBOLS
963d8817e4Smiod #define RTYPE2HOWTO(cache_ptr, dst) xcoff_rtype2howto (cache_ptr, dst)
973d8817e4Smiod #define coff_mkobject _bfd_xcoff_mkobject
983d8817e4Smiod #define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
993d8817e4Smiod #define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
1003d8817e4Smiod #define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup
1013d8817e4Smiod #ifdef AIX_CORE
1023d8817e4Smiod extern const bfd_target * rs6000coff_core_p
1033d8817e4Smiod   PARAMS ((bfd *abfd));
1043d8817e4Smiod extern bfd_boolean rs6000coff_core_file_matches_executable_p
1053d8817e4Smiod   PARAMS ((bfd *cbfd, bfd *ebfd));
1063d8817e4Smiod extern char *rs6000coff_core_file_failing_command
1073d8817e4Smiod   PARAMS ((bfd *abfd));
1083d8817e4Smiod extern int rs6000coff_core_file_failing_signal
1093d8817e4Smiod   PARAMS ((bfd *abfd));
1103d8817e4Smiod #define CORE_FILE_P rs6000coff_core_p
1113d8817e4Smiod #define coff_core_file_failing_command \
1123d8817e4Smiod   rs6000coff_core_file_failing_command
1133d8817e4Smiod #define coff_core_file_failing_signal \
1143d8817e4Smiod   rs6000coff_core_file_failing_signal
1153d8817e4Smiod #define coff_core_file_matches_executable_p \
1163d8817e4Smiod   rs6000coff_core_file_matches_executable_p
1173d8817e4Smiod #else
1183d8817e4Smiod #define CORE_FILE_P _bfd_dummy_target
1193d8817e4Smiod #define coff_core_file_failing_command \
1203d8817e4Smiod   _bfd_nocore_core_file_failing_command
1213d8817e4Smiod #define coff_core_file_failing_signal \
1223d8817e4Smiod   _bfd_nocore_core_file_failing_signal
1233d8817e4Smiod #define coff_core_file_matches_executable_p \
1243d8817e4Smiod   _bfd_nocore_core_file_matches_executable_p
1253d8817e4Smiod #endif
1263d8817e4Smiod #define coff_SWAP_sym_in _bfd_xcoff_swap_sym_in
1273d8817e4Smiod #define coff_SWAP_sym_out _bfd_xcoff_swap_sym_out
1283d8817e4Smiod #define coff_SWAP_aux_in _bfd_xcoff_swap_aux_in
1293d8817e4Smiod #define coff_SWAP_aux_out _bfd_xcoff_swap_aux_out
1303d8817e4Smiod #define coff_swap_reloc_in xcoff_swap_reloc_in
1313d8817e4Smiod #define coff_swap_reloc_out xcoff_swap_reloc_out
1323d8817e4Smiod #define NO_COFF_RELOCS
1333d8817e4Smiod 
1343d8817e4Smiod #include "coffcode.h"
1353d8817e4Smiod 
1363d8817e4Smiod /* The main body of code is in coffcode.h.  */
1373d8817e4Smiod 
1383d8817e4Smiod static const char *normalize_filename
1393d8817e4Smiod   PARAMS ((bfd *));
1403d8817e4Smiod static bfd_boolean xcoff_write_armap_old
1413d8817e4Smiod   PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
1423d8817e4Smiod static bfd_boolean xcoff_write_armap_big
1433d8817e4Smiod   PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
1443d8817e4Smiod static bfd_boolean xcoff_write_archive_contents_old
1453d8817e4Smiod   PARAMS ((bfd *));
1463d8817e4Smiod static bfd_boolean xcoff_write_archive_contents_big
1473d8817e4Smiod   PARAMS ((bfd *));
1483d8817e4Smiod static void xcoff_swap_ldhdr_in
1493d8817e4Smiod   PARAMS ((bfd *, const PTR, struct internal_ldhdr *));
1503d8817e4Smiod static void xcoff_swap_ldhdr_out
1513d8817e4Smiod   PARAMS ((bfd *, const struct internal_ldhdr *, PTR));
1523d8817e4Smiod static void xcoff_swap_ldsym_in
1533d8817e4Smiod   PARAMS ((bfd *, const PTR, struct internal_ldsym *));
1543d8817e4Smiod static void xcoff_swap_ldsym_out
1553d8817e4Smiod   PARAMS ((bfd *, const struct internal_ldsym *, PTR));
1563d8817e4Smiod static void xcoff_swap_ldrel_in
1573d8817e4Smiod   PARAMS ((bfd *, const PTR, struct internal_ldrel *));
1583d8817e4Smiod static void xcoff_swap_ldrel_out
1593d8817e4Smiod   PARAMS ((bfd *, const struct internal_ldrel *, PTR));
1603d8817e4Smiod static bfd_boolean xcoff_ppc_relocate_section
1613d8817e4Smiod   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
1623d8817e4Smiod 	   struct internal_reloc *, struct internal_syment *, asection **));
1633d8817e4Smiod static bfd_boolean _bfd_xcoff_put_ldsymbol_name
1643d8817e4Smiod   PARAMS ((bfd *, struct xcoff_loader_info *, struct internal_ldsym *,
1653d8817e4Smiod 	   const char *));
1663d8817e4Smiod static asection *xcoff_create_csect_from_smclas
1673d8817e4Smiod   PARAMS ((bfd *, union internal_auxent *, const char *));
1683d8817e4Smiod static bfd_boolean xcoff_is_lineno_count_overflow
1693d8817e4Smiod   PARAMS ((bfd *, bfd_vma));
1703d8817e4Smiod static bfd_boolean xcoff_is_reloc_count_overflow
1713d8817e4Smiod   PARAMS ((bfd *, bfd_vma));
1723d8817e4Smiod static bfd_vma xcoff_loader_symbol_offset
1733d8817e4Smiod   PARAMS ((bfd *, struct internal_ldhdr *));
1743d8817e4Smiod static bfd_vma xcoff_loader_reloc_offset
1753d8817e4Smiod   PARAMS ((bfd *, struct internal_ldhdr *));
1763d8817e4Smiod static bfd_boolean xcoff_generate_rtinit
1773d8817e4Smiod   PARAMS ((bfd *, const char *, const char *, bfd_boolean));
1783d8817e4Smiod static bfd_boolean do_pad
1793d8817e4Smiod   PARAMS ((bfd *, unsigned int));
1803d8817e4Smiod static bfd_boolean do_copy
1813d8817e4Smiod   PARAMS ((bfd *, bfd *));
1823d8817e4Smiod static bfd_boolean do_shared_object_padding
1833d8817e4Smiod   PARAMS ((bfd *, bfd *, file_ptr *, int));
1843d8817e4Smiod 
1853d8817e4Smiod /* Relocation functions */
1863d8817e4Smiod static bfd_boolean xcoff_reloc_type_br
1873d8817e4Smiod   PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
1883d8817e4Smiod 
1893d8817e4Smiod static bfd_boolean xcoff_complain_overflow_dont_func
1903d8817e4Smiod   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
1913d8817e4Smiod static bfd_boolean xcoff_complain_overflow_bitfield_func
1923d8817e4Smiod   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
1933d8817e4Smiod static bfd_boolean xcoff_complain_overflow_signed_func
1943d8817e4Smiod   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
1953d8817e4Smiod static bfd_boolean xcoff_complain_overflow_unsigned_func
1963d8817e4Smiod   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
1973d8817e4Smiod 
1983d8817e4Smiod bfd_boolean (*xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
1993d8817e4Smiod   PARAMS ((XCOFF_RELOC_FUNCTION_ARGS)) =
2003d8817e4Smiod {
2013d8817e4Smiod   xcoff_reloc_type_pos,	 /* R_POS   (0x00) */
2023d8817e4Smiod   xcoff_reloc_type_neg,	 /* R_NEG   (0x01) */
2033d8817e4Smiod   xcoff_reloc_type_rel,	 /* R_REL   (0x02) */
2043d8817e4Smiod   xcoff_reloc_type_toc,	 /* R_TOC   (0x03) */
2053d8817e4Smiod   xcoff_reloc_type_fail, /* R_RTB   (0x04) */
2063d8817e4Smiod   xcoff_reloc_type_toc,	 /* R_GL    (0x05) */
2073d8817e4Smiod   xcoff_reloc_type_toc,	 /* R_TCL   (0x06) */
2083d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x07) */
2093d8817e4Smiod   xcoff_reloc_type_ba,	 /* R_BA    (0x08) */
2103d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x09) */
2113d8817e4Smiod   xcoff_reloc_type_br,	 /* R_BR    (0x0a) */
2123d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x0b) */
2133d8817e4Smiod   xcoff_reloc_type_pos,	 /* R_RL    (0x0c) */
2143d8817e4Smiod   xcoff_reloc_type_pos,	 /* R_RLA   (0x0d) */
2153d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x0e) */
2163d8817e4Smiod   xcoff_reloc_type_noop, /* R_REF   (0x0f) */
2173d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x10) */
2183d8817e4Smiod   xcoff_reloc_type_fail, /*	    (0x11) */
2193d8817e4Smiod   xcoff_reloc_type_toc,	 /* R_TRL   (0x12) */
2203d8817e4Smiod   xcoff_reloc_type_toc,	 /* R_TRLA  (0x13) */
2213d8817e4Smiod   xcoff_reloc_type_fail, /* R_RRTBI (0x14) */
2223d8817e4Smiod   xcoff_reloc_type_fail, /* R_RRTBA (0x15) */
2233d8817e4Smiod   xcoff_reloc_type_ba,	 /* R_CAI   (0x16) */
2243d8817e4Smiod   xcoff_reloc_type_crel, /* R_CREL  (0x17) */
2253d8817e4Smiod   xcoff_reloc_type_ba,	 /* R_RBA   (0x18) */
2263d8817e4Smiod   xcoff_reloc_type_ba,	 /* R_RBAC  (0x19) */
2273d8817e4Smiod   xcoff_reloc_type_br,	 /* R_RBR   (0x1a) */
2283d8817e4Smiod   xcoff_reloc_type_ba,	 /* R_RBRC  (0x1b) */
2293d8817e4Smiod };
2303d8817e4Smiod 
2313d8817e4Smiod bfd_boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW])
2323d8817e4Smiod   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)) =
2333d8817e4Smiod {
2343d8817e4Smiod   xcoff_complain_overflow_dont_func,
2353d8817e4Smiod   xcoff_complain_overflow_bitfield_func,
2363d8817e4Smiod   xcoff_complain_overflow_signed_func,
2373d8817e4Smiod   xcoff_complain_overflow_unsigned_func,
2383d8817e4Smiod };
2393d8817e4Smiod 
2403d8817e4Smiod /* We use our own tdata type.  Its first field is the COFF tdata type,
2413d8817e4Smiod    so the COFF routines are compatible.  */
2423d8817e4Smiod 
2433d8817e4Smiod bfd_boolean
_bfd_xcoff_mkobject(abfd)2443d8817e4Smiod _bfd_xcoff_mkobject (abfd)
2453d8817e4Smiod      bfd *abfd;
2463d8817e4Smiod {
2473d8817e4Smiod   coff_data_type *coff;
2483d8817e4Smiod   bfd_size_type amt = sizeof (struct xcoff_tdata);
2493d8817e4Smiod 
2503d8817e4Smiod   abfd->tdata.xcoff_obj_data = (struct xcoff_tdata *) bfd_zalloc (abfd, amt);
2513d8817e4Smiod   if (abfd->tdata.xcoff_obj_data == NULL)
2523d8817e4Smiod     return FALSE;
2533d8817e4Smiod   coff = coff_data (abfd);
2543d8817e4Smiod   coff->symbols = (coff_symbol_type *) NULL;
2553d8817e4Smiod   coff->conversion_table = (unsigned int *) NULL;
2563d8817e4Smiod   coff->raw_syments = (struct coff_ptr_struct *) NULL;
2573d8817e4Smiod   coff->relocbase = 0;
2583d8817e4Smiod 
2593d8817e4Smiod   xcoff_data (abfd)->modtype = ('1' << 8) | 'L';
2603d8817e4Smiod 
2613d8817e4Smiod   /* We set cputype to -1 to indicate that it has not been
2623d8817e4Smiod      initialized.  */
2633d8817e4Smiod   xcoff_data (abfd)->cputype = -1;
2643d8817e4Smiod 
2653d8817e4Smiod   xcoff_data (abfd)->csects = NULL;
2663d8817e4Smiod   xcoff_data (abfd)->debug_indices = NULL;
2673d8817e4Smiod 
2683d8817e4Smiod   /* text section alignment is different than the default */
2693d8817e4Smiod   bfd_xcoff_text_align_power (abfd) = 2;
2703d8817e4Smiod 
2713d8817e4Smiod   return TRUE;
2723d8817e4Smiod }
2733d8817e4Smiod 
2743d8817e4Smiod /* Copy XCOFF data from one BFD to another.  */
2753d8817e4Smiod 
2763d8817e4Smiod bfd_boolean
_bfd_xcoff_copy_private_bfd_data(ibfd,obfd)2773d8817e4Smiod _bfd_xcoff_copy_private_bfd_data (ibfd, obfd)
2783d8817e4Smiod      bfd *ibfd;
2793d8817e4Smiod      bfd *obfd;
2803d8817e4Smiod {
2813d8817e4Smiod   struct xcoff_tdata *ix, *ox;
2823d8817e4Smiod   asection *sec;
2833d8817e4Smiod 
2843d8817e4Smiod   if (ibfd->xvec != obfd->xvec)
2853d8817e4Smiod     return TRUE;
2863d8817e4Smiod   ix = xcoff_data (ibfd);
2873d8817e4Smiod   ox = xcoff_data (obfd);
2883d8817e4Smiod   ox->full_aouthdr = ix->full_aouthdr;
2893d8817e4Smiod   ox->toc = ix->toc;
2903d8817e4Smiod   if (ix->sntoc == 0)
2913d8817e4Smiod     ox->sntoc = 0;
2923d8817e4Smiod   else
2933d8817e4Smiod     {
2943d8817e4Smiod       sec = coff_section_from_bfd_index (ibfd, ix->sntoc);
2953d8817e4Smiod       if (sec == NULL)
2963d8817e4Smiod 	ox->sntoc = 0;
2973d8817e4Smiod       else
2983d8817e4Smiod 	ox->sntoc = sec->output_section->target_index;
2993d8817e4Smiod     }
3003d8817e4Smiod   if (ix->snentry == 0)
3013d8817e4Smiod     ox->snentry = 0;
3023d8817e4Smiod   else
3033d8817e4Smiod     {
3043d8817e4Smiod       sec = coff_section_from_bfd_index (ibfd, ix->snentry);
3053d8817e4Smiod       if (sec == NULL)
3063d8817e4Smiod 	ox->snentry = 0;
3073d8817e4Smiod       else
3083d8817e4Smiod 	ox->snentry = sec->output_section->target_index;
3093d8817e4Smiod     }
3103d8817e4Smiod   bfd_xcoff_text_align_power (obfd) = bfd_xcoff_text_align_power (ibfd);
3113d8817e4Smiod   bfd_xcoff_data_align_power (obfd) = bfd_xcoff_data_align_power (ibfd);
3123d8817e4Smiod   ox->modtype = ix->modtype;
3133d8817e4Smiod   ox->cputype = ix->cputype;
3143d8817e4Smiod   ox->maxdata = ix->maxdata;
3153d8817e4Smiod   ox->maxstack = ix->maxstack;
3163d8817e4Smiod   return TRUE;
3173d8817e4Smiod }
3183d8817e4Smiod 
3193d8817e4Smiod /* I don't think XCOFF really has a notion of local labels based on
3203d8817e4Smiod    name.  This will mean that ld -X doesn't actually strip anything.
3213d8817e4Smiod    The AIX native linker does not have a -X option, and it ignores the
3223d8817e4Smiod    -x option.  */
3233d8817e4Smiod 
3243d8817e4Smiod bfd_boolean
_bfd_xcoff_is_local_label_name(abfd,name)3253d8817e4Smiod _bfd_xcoff_is_local_label_name (abfd, name)
3263d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
3273d8817e4Smiod      const char *name ATTRIBUTE_UNUSED;
3283d8817e4Smiod {
3293d8817e4Smiod   return FALSE;
3303d8817e4Smiod }
3313d8817e4Smiod 
3323d8817e4Smiod void
_bfd_xcoff_swap_sym_in(abfd,ext1,in1)3333d8817e4Smiod _bfd_xcoff_swap_sym_in (abfd, ext1, in1)
3343d8817e4Smiod      bfd *abfd;
3353d8817e4Smiod      PTR ext1;
3363d8817e4Smiod      PTR in1;
3373d8817e4Smiod {
3383d8817e4Smiod   SYMENT *ext = (SYMENT *)ext1;
3393d8817e4Smiod   struct internal_syment * in = (struct internal_syment *)in1;
3403d8817e4Smiod 
3413d8817e4Smiod   if (ext->e.e_name[0] != 0)
3423d8817e4Smiod     {
3433d8817e4Smiod       memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN);
3443d8817e4Smiod     }
3453d8817e4Smiod   else
3463d8817e4Smiod     {
3473d8817e4Smiod       in->_n._n_n._n_zeroes = 0;
3483d8817e4Smiod       in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset);
3493d8817e4Smiod     }
3503d8817e4Smiod 
3513d8817e4Smiod   in->n_value = H_GET_32 (abfd, ext->e_value);
3523d8817e4Smiod   in->n_scnum = H_GET_16 (abfd, ext->e_scnum);
3533d8817e4Smiod   in->n_type = H_GET_16 (abfd, ext->e_type);
3543d8817e4Smiod   in->n_sclass = H_GET_8 (abfd, ext->e_sclass);
3553d8817e4Smiod   in->n_numaux = H_GET_8 (abfd, ext->e_numaux);
3563d8817e4Smiod }
3573d8817e4Smiod 
3583d8817e4Smiod unsigned int
_bfd_xcoff_swap_sym_out(abfd,inp,extp)3593d8817e4Smiod _bfd_xcoff_swap_sym_out (abfd, inp, extp)
3603d8817e4Smiod      bfd *abfd;
3613d8817e4Smiod      PTR inp;
3623d8817e4Smiod      PTR extp;
3633d8817e4Smiod {
3643d8817e4Smiod   struct internal_syment *in = (struct internal_syment *)inp;
3653d8817e4Smiod   SYMENT *ext =(SYMENT *)extp;
3663d8817e4Smiod 
3673d8817e4Smiod   if (in->_n._n_name[0] != 0)
3683d8817e4Smiod     {
3693d8817e4Smiod       memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN);
3703d8817e4Smiod     }
3713d8817e4Smiod   else
3723d8817e4Smiod     {
3733d8817e4Smiod       H_PUT_32 (abfd, 0, ext->e.e.e_zeroes);
3743d8817e4Smiod       H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset);
3753d8817e4Smiod     }
3763d8817e4Smiod 
3773d8817e4Smiod   H_PUT_32 (abfd, in->n_value, ext->e_value);
3783d8817e4Smiod   H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);
3793d8817e4Smiod   H_PUT_16 (abfd, in->n_type, ext->e_type);
3803d8817e4Smiod   H_PUT_8 (abfd, in->n_sclass, ext->e_sclass);
3813d8817e4Smiod   H_PUT_8 (abfd, in->n_numaux, ext->e_numaux);
3823d8817e4Smiod   return bfd_coff_symesz (abfd);
3833d8817e4Smiod }
3843d8817e4Smiod 
3853d8817e4Smiod void
_bfd_xcoff_swap_aux_in(abfd,ext1,type,class,indx,numaux,in1)3863d8817e4Smiod _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
3873d8817e4Smiod      bfd *abfd;
3883d8817e4Smiod      PTR ext1;
3893d8817e4Smiod      int type;
3903d8817e4Smiod      int class;
3913d8817e4Smiod      int indx;
3923d8817e4Smiod      int numaux;
3933d8817e4Smiod      PTR in1;
3943d8817e4Smiod {
3953d8817e4Smiod   AUXENT * ext = (AUXENT *)ext1;
3963d8817e4Smiod   union internal_auxent *in = (union internal_auxent *)in1;
3973d8817e4Smiod 
3983d8817e4Smiod   switch (class)
3993d8817e4Smiod     {
4003d8817e4Smiod     case C_FILE:
4013d8817e4Smiod       if (ext->x_file.x_fname[0] == 0)
4023d8817e4Smiod 	{
4033d8817e4Smiod 	  in->x_file.x_n.x_zeroes = 0;
4043d8817e4Smiod 	  in->x_file.x_n.x_offset =
4053d8817e4Smiod 	    H_GET_32 (abfd, ext->x_file.x_n.x_offset);
4063d8817e4Smiod 	}
4073d8817e4Smiod       else
4083d8817e4Smiod 	{
4093d8817e4Smiod 	  if (numaux > 1)
4103d8817e4Smiod 	    {
4113d8817e4Smiod 	      if (indx == 0)
4123d8817e4Smiod 		memcpy (in->x_file.x_fname, ext->x_file.x_fname,
4133d8817e4Smiod 			numaux * sizeof (AUXENT));
4143d8817e4Smiod 	    }
4153d8817e4Smiod 	  else
4163d8817e4Smiod 	    {
4173d8817e4Smiod 	      memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
4183d8817e4Smiod 	    }
4193d8817e4Smiod 	}
4203d8817e4Smiod       goto end;
4213d8817e4Smiod 
4223d8817e4Smiod       /* RS/6000 "csect" auxents */
4233d8817e4Smiod     case C_EXT:
4243d8817e4Smiod     case C_HIDEXT:
4253d8817e4Smiod       if (indx + 1 == numaux)
4263d8817e4Smiod 	{
4273d8817e4Smiod 	  in->x_csect.x_scnlen.l = H_GET_32 (abfd, ext->x_csect.x_scnlen);
4283d8817e4Smiod 	  in->x_csect.x_parmhash = H_GET_32 (abfd, ext->x_csect.x_parmhash);
4293d8817e4Smiod 	  in->x_csect.x_snhash   = H_GET_16 (abfd, ext->x_csect.x_snhash);
4303d8817e4Smiod 	  /* We don't have to hack bitfields in x_smtyp because it's
4313d8817e4Smiod 	     defined by shifts-and-ands, which are equivalent on all
4323d8817e4Smiod 	     byte orders.  */
4333d8817e4Smiod 	  in->x_csect.x_smtyp    = H_GET_8 (abfd, ext->x_csect.x_smtyp);
4343d8817e4Smiod 	  in->x_csect.x_smclas   = H_GET_8 (abfd, ext->x_csect.x_smclas);
4353d8817e4Smiod 	  in->x_csect.x_stab     = H_GET_32 (abfd, ext->x_csect.x_stab);
4363d8817e4Smiod 	  in->x_csect.x_snstab   = H_GET_16 (abfd, ext->x_csect.x_snstab);
4373d8817e4Smiod 	  goto end;
4383d8817e4Smiod 	}
4393d8817e4Smiod       break;
4403d8817e4Smiod 
4413d8817e4Smiod     case C_STAT:
4423d8817e4Smiod     case C_LEAFSTAT:
4433d8817e4Smiod     case C_HIDDEN:
4443d8817e4Smiod       if (type == T_NULL)
4453d8817e4Smiod 	{
4463d8817e4Smiod 	  in->x_scn.x_scnlen = H_GET_32 (abfd, ext->x_scn.x_scnlen);
4473d8817e4Smiod 	  in->x_scn.x_nreloc = H_GET_16 (abfd, ext->x_scn.x_nreloc);
4483d8817e4Smiod 	  in->x_scn.x_nlinno = H_GET_16 (abfd, ext->x_scn.x_nlinno);
4493d8817e4Smiod 	  /* PE defines some extra fields; we zero them out for
4503d8817e4Smiod 	     safety.  */
4513d8817e4Smiod 	  in->x_scn.x_checksum = 0;
4523d8817e4Smiod 	  in->x_scn.x_associated = 0;
4533d8817e4Smiod 	  in->x_scn.x_comdat = 0;
4543d8817e4Smiod 
4553d8817e4Smiod 	  goto end;
4563d8817e4Smiod 	}
4573d8817e4Smiod       break;
4583d8817e4Smiod     }
4593d8817e4Smiod 
4603d8817e4Smiod   in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
4613d8817e4Smiod   in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
4623d8817e4Smiod 
4633d8817e4Smiod   if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
4643d8817e4Smiod     {
4653d8817e4Smiod       in->x_sym.x_fcnary.x_fcn.x_lnnoptr =
4663d8817e4Smiod 	H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
4673d8817e4Smiod       in->x_sym.x_fcnary.x_fcn.x_endndx.l =
4683d8817e4Smiod 	H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx);
4693d8817e4Smiod     }
4703d8817e4Smiod   else
4713d8817e4Smiod     {
4723d8817e4Smiod       in->x_sym.x_fcnary.x_ary.x_dimen[0] =
4733d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
4743d8817e4Smiod       in->x_sym.x_fcnary.x_ary.x_dimen[1] =
4753d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
4763d8817e4Smiod       in->x_sym.x_fcnary.x_ary.x_dimen[2] =
4773d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
4783d8817e4Smiod       in->x_sym.x_fcnary.x_ary.x_dimen[3] =
4793d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
4803d8817e4Smiod     }
4813d8817e4Smiod 
4823d8817e4Smiod   if (ISFCN (type))
4833d8817e4Smiod     {
4843d8817e4Smiod       in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize);
4853d8817e4Smiod     }
4863d8817e4Smiod   else
4873d8817e4Smiod     {
4883d8817e4Smiod       in->x_sym.x_misc.x_lnsz.x_lnno =
4893d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_lnno);
4903d8817e4Smiod       in->x_sym.x_misc.x_lnsz.x_size =
4913d8817e4Smiod 	H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size);
4923d8817e4Smiod     }
4933d8817e4Smiod 
4943d8817e4Smiod  end: ;
4953d8817e4Smiod   /* The semicolon is because MSVC doesn't like labels at
4963d8817e4Smiod      end of block.  */
4973d8817e4Smiod }
4983d8817e4Smiod 
4993d8817e4Smiod 
5003d8817e4Smiod unsigned int _bfd_xcoff_swap_aux_out
5013d8817e4Smiod   PARAMS ((bfd *, PTR, int, int, int, int, PTR));
5023d8817e4Smiod 
5033d8817e4Smiod unsigned int
_bfd_xcoff_swap_aux_out(abfd,inp,type,class,indx,numaux,extp)5043d8817e4Smiod _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
5053d8817e4Smiod      bfd * abfd;
5063d8817e4Smiod      PTR   inp;
5073d8817e4Smiod      int   type;
5083d8817e4Smiod      int   class;
5093d8817e4Smiod      int   indx ATTRIBUTE_UNUSED;
5103d8817e4Smiod      int   numaux ATTRIBUTE_UNUSED;
5113d8817e4Smiod      PTR   extp;
5123d8817e4Smiod {
5133d8817e4Smiod   union internal_auxent *in = (union internal_auxent *)inp;
5143d8817e4Smiod   AUXENT *ext = (AUXENT *)extp;
5153d8817e4Smiod 
5163d8817e4Smiod   memset ((PTR)ext, 0, bfd_coff_auxesz (abfd));
5173d8817e4Smiod   switch (class)
5183d8817e4Smiod     {
5193d8817e4Smiod     case C_FILE:
5203d8817e4Smiod       if (in->x_file.x_fname[0] == 0)
5213d8817e4Smiod 	{
5223d8817e4Smiod 	  H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
5233d8817e4Smiod 	  H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
5243d8817e4Smiod 	}
5253d8817e4Smiod       else
5263d8817e4Smiod 	{
5273d8817e4Smiod 	  memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
5283d8817e4Smiod 	}
5293d8817e4Smiod       goto end;
5303d8817e4Smiod 
5313d8817e4Smiod       /* RS/6000 "csect" auxents */
5323d8817e4Smiod     case C_EXT:
5333d8817e4Smiod     case C_HIDEXT:
5343d8817e4Smiod       if (indx + 1 == numaux)
5353d8817e4Smiod 	{
5363d8817e4Smiod 	  H_PUT_32 (abfd, in->x_csect.x_scnlen.l, ext->x_csect.x_scnlen);
5373d8817e4Smiod 	  H_PUT_32 (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
5383d8817e4Smiod 	  H_PUT_16 (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
5393d8817e4Smiod 	  /* We don't have to hack bitfields in x_smtyp because it's
5403d8817e4Smiod 	     defined by shifts-and-ands, which are equivalent on all
5413d8817e4Smiod 	     byte orders.  */
5423d8817e4Smiod 	  H_PUT_8 (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
5433d8817e4Smiod 	  H_PUT_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
5443d8817e4Smiod 	  H_PUT_32 (abfd, in->x_csect.x_stab, ext->x_csect.x_stab);
5453d8817e4Smiod 	  H_PUT_16 (abfd, in->x_csect.x_snstab, ext->x_csect.x_snstab);
5463d8817e4Smiod 	  goto end;
5473d8817e4Smiod 	}
5483d8817e4Smiod       break;
5493d8817e4Smiod 
5503d8817e4Smiod     case C_STAT:
5513d8817e4Smiod     case C_LEAFSTAT:
5523d8817e4Smiod     case C_HIDDEN:
5533d8817e4Smiod       if (type == T_NULL)
5543d8817e4Smiod 	{
5553d8817e4Smiod 	  H_PUT_32 (abfd, in->x_scn.x_scnlen, ext->x_scn.x_scnlen);
5563d8817e4Smiod 	  H_PUT_16 (abfd, in->x_scn.x_nreloc, ext->x_scn.x_nreloc);
5573d8817e4Smiod 	  H_PUT_16 (abfd, in->x_scn.x_nlinno, ext->x_scn.x_nlinno);
5583d8817e4Smiod 	  goto end;
5593d8817e4Smiod 	}
5603d8817e4Smiod       break;
5613d8817e4Smiod     }
5623d8817e4Smiod 
5633d8817e4Smiod   H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
5643d8817e4Smiod   H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
5653d8817e4Smiod 
5663d8817e4Smiod   if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
5673d8817e4Smiod     {
5683d8817e4Smiod       H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
5693d8817e4Smiod 		ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
5703d8817e4Smiod       H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
5713d8817e4Smiod 		ext->x_sym.x_fcnary.x_fcn.x_endndx);
5723d8817e4Smiod     }
5733d8817e4Smiod   else
5743d8817e4Smiod     {
5753d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
5763d8817e4Smiod 		ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
5773d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
5783d8817e4Smiod 		ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
5793d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
5803d8817e4Smiod 		ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
5813d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
5823d8817e4Smiod 		ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
5833d8817e4Smiod     }
5843d8817e4Smiod 
5853d8817e4Smiod   if (ISFCN (type))
5863d8817e4Smiod     H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize);
5873d8817e4Smiod   else
5883d8817e4Smiod     {
5893d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
5903d8817e4Smiod 		ext->x_sym.x_misc.x_lnsz.x_lnno);
5913d8817e4Smiod       H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_size,
5923d8817e4Smiod 		ext->x_sym.x_misc.x_lnsz.x_size);
5933d8817e4Smiod     }
5943d8817e4Smiod 
5953d8817e4Smiod end:
5963d8817e4Smiod   return bfd_coff_auxesz (abfd);
5973d8817e4Smiod }
5983d8817e4Smiod 
5993d8817e4Smiod 
6003d8817e4Smiod 
6013d8817e4Smiod /* The XCOFF reloc table.  Actually, XCOFF relocations specify the
6023d8817e4Smiod    bitsize and whether they are signed or not, along with a
6033d8817e4Smiod    conventional type.  This table is for the types, which are used for
6043d8817e4Smiod    different algorithms for putting in the reloc.  Many of these
6053d8817e4Smiod    relocs need special_function entries, which I have not written.  */
6063d8817e4Smiod 
6073d8817e4Smiod 
6083d8817e4Smiod reloc_howto_type xcoff_howto_table[] =
6093d8817e4Smiod {
6103d8817e4Smiod   /* Standard 32 bit relocation.  */
6113d8817e4Smiod   HOWTO (R_POS,			/* type */
6123d8817e4Smiod 	 0,			/* rightshift */
6133d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
6143d8817e4Smiod 	 32,			/* bitsize */
6153d8817e4Smiod 	 FALSE,			/* pc_relative */
6163d8817e4Smiod 	 0,			/* bitpos */
6173d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
6183d8817e4Smiod 	 0,			/* special_function */
6193d8817e4Smiod 	 "R_POS",		/* name */
6203d8817e4Smiod 	 TRUE,			/* partial_inplace */
6213d8817e4Smiod 	 0xffffffff,		/* src_mask */
6223d8817e4Smiod 	 0xffffffff,		/* dst_mask */
6233d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6243d8817e4Smiod 
6253d8817e4Smiod   /* 32 bit relocation, but store negative value.  */
6263d8817e4Smiod   HOWTO (R_NEG,			/* type */
6273d8817e4Smiod 	 0,			/* rightshift */
6283d8817e4Smiod 	 -2,			/* size (0 = byte, 1 = short, 2 = long) */
6293d8817e4Smiod 	 32,			/* bitsize */
6303d8817e4Smiod 	 FALSE,			/* pc_relative */
6313d8817e4Smiod 	 0,			/* bitpos */
6323d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
6333d8817e4Smiod 	 0,			/* special_function */
6343d8817e4Smiod 	 "R_NEG",		/* name */
6353d8817e4Smiod 	 TRUE,			/* partial_inplace */
6363d8817e4Smiod 	 0xffffffff,		/* src_mask */
6373d8817e4Smiod 	 0xffffffff,		/* dst_mask */
6383d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6393d8817e4Smiod 
6403d8817e4Smiod   /* 32 bit PC relative relocation.  */
6413d8817e4Smiod   HOWTO (R_REL,			/* type */
6423d8817e4Smiod 	 0,			/* rightshift */
6433d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
6443d8817e4Smiod 	 32,			/* bitsize */
6453d8817e4Smiod 	 TRUE,			/* pc_relative */
6463d8817e4Smiod 	 0,			/* bitpos */
6473d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
6483d8817e4Smiod 	 0,			/* special_function */
6493d8817e4Smiod 	 "R_REL",		/* name */
6503d8817e4Smiod 	 TRUE,			/* partial_inplace */
6513d8817e4Smiod 	 0xffffffff,		/* src_mask */
6523d8817e4Smiod 	 0xffffffff,		/* dst_mask */
6533d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6543d8817e4Smiod 
6553d8817e4Smiod   /* 16 bit TOC relative relocation.  */
6563d8817e4Smiod   HOWTO (R_TOC,			/* type */
6573d8817e4Smiod 	 0,			/* rightshift */
6583d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
6593d8817e4Smiod 	 16,			/* bitsize */
6603d8817e4Smiod 	 FALSE,			/* pc_relative */
6613d8817e4Smiod 	 0,			/* bitpos */
6623d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
6633d8817e4Smiod 	 0,			/* special_function */
6643d8817e4Smiod 	 "R_TOC",		/* name */
6653d8817e4Smiod 	 TRUE,			/* partial_inplace */
6663d8817e4Smiod 	 0xffff,		/* src_mask */
6673d8817e4Smiod 	 0xffff,		/* dst_mask */
6683d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6693d8817e4Smiod 
6703d8817e4Smiod   /* I don't really know what this is.  */
6713d8817e4Smiod   HOWTO (R_RTB,			/* type */
6723d8817e4Smiod 	 1,			/* rightshift */
6733d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
6743d8817e4Smiod 	 32,			/* bitsize */
6753d8817e4Smiod 	 FALSE,			/* pc_relative */
6763d8817e4Smiod 	 0,			/* bitpos */
6773d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
6783d8817e4Smiod 	 0,			/* special_function */
6793d8817e4Smiod 	 "R_RTB",		/* name */
6803d8817e4Smiod 	 TRUE,			/* partial_inplace */
6813d8817e4Smiod 	 0xffffffff,		/* src_mask */
6823d8817e4Smiod 	 0xffffffff,		/* dst_mask */
6833d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6843d8817e4Smiod 
6853d8817e4Smiod   /* External TOC relative symbol.  */
6863d8817e4Smiod   HOWTO (R_GL,			/* type */
6873d8817e4Smiod 	 0,			/* rightshift */
6883d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
6893d8817e4Smiod 	 16,			/* bitsize */
6903d8817e4Smiod 	 FALSE,			/* pc_relative */
6913d8817e4Smiod 	 0,			/* bitpos */
6923d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
6933d8817e4Smiod 	 0,			/* special_function */
6943d8817e4Smiod 	 "R_GL",		/* name */
6953d8817e4Smiod 	 TRUE,			/* partial_inplace */
6963d8817e4Smiod 	 0xffff,		/* src_mask */
6973d8817e4Smiod 	 0xffff,		/* dst_mask */
6983d8817e4Smiod 	 FALSE),		/* pcrel_offset */
6993d8817e4Smiod 
7003d8817e4Smiod   /* Local TOC relative symbol.	 */
7013d8817e4Smiod   HOWTO (R_TCL,			/* type */
7023d8817e4Smiod 	 0,			/* rightshift */
7033d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
7043d8817e4Smiod 	 16,			/* bitsize */
7053d8817e4Smiod 	 FALSE,			/* pc_relative */
7063d8817e4Smiod 	 0,			/* bitpos */
7073d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
7083d8817e4Smiod 	 0,			/* special_function */
7093d8817e4Smiod 	 "R_TCL",		/* name */
7103d8817e4Smiod 	 TRUE,			/* partial_inplace */
7113d8817e4Smiod 	 0xffff,		/* src_mask */
7123d8817e4Smiod 	 0xffff,		/* dst_mask */
7133d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7143d8817e4Smiod 
7153d8817e4Smiod   EMPTY_HOWTO (7),
7163d8817e4Smiod 
7173d8817e4Smiod   /* Non modifiable absolute branch.  */
7183d8817e4Smiod   HOWTO (R_BA,			/* type */
7193d8817e4Smiod 	 0,			/* rightshift */
7203d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
7213d8817e4Smiod 	 26,			/* bitsize */
7223d8817e4Smiod 	 FALSE,			/* pc_relative */
7233d8817e4Smiod 	 0,			/* bitpos */
7243d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
7253d8817e4Smiod 	 0,			/* special_function */
7263d8817e4Smiod 	 "R_BA_26",		/* name */
7273d8817e4Smiod 	 TRUE,			/* partial_inplace */
7283d8817e4Smiod 	 0x03fffffc,		/* src_mask */
7293d8817e4Smiod 	 0x03fffffc,		/* dst_mask */
7303d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7313d8817e4Smiod 
7323d8817e4Smiod   EMPTY_HOWTO (9),
7333d8817e4Smiod 
7343d8817e4Smiod   /* Non modifiable relative branch.  */
7353d8817e4Smiod   HOWTO (R_BR,			/* type */
7363d8817e4Smiod 	 0,			/* rightshift */
7373d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
7383d8817e4Smiod 	 26,			/* bitsize */
7393d8817e4Smiod 	 TRUE,			/* pc_relative */
7403d8817e4Smiod 	 0,			/* bitpos */
7413d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
7423d8817e4Smiod 	 0,			/* special_function */
7433d8817e4Smiod 	 "R_BR",		/* name */
7443d8817e4Smiod 	 TRUE,			/* partial_inplace */
7453d8817e4Smiod 	 0x03fffffc,		/* src_mask */
7463d8817e4Smiod 	 0x03fffffc,		/* dst_mask */
7473d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7483d8817e4Smiod 
7493d8817e4Smiod   EMPTY_HOWTO (0xb),
7503d8817e4Smiod 
7513d8817e4Smiod   /* Indirect load.  */
7523d8817e4Smiod   HOWTO (R_RL,			/* type */
7533d8817e4Smiod 	 0,			/* rightshift */
7543d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
7553d8817e4Smiod 	 16,			/* bitsize */
7563d8817e4Smiod 	 FALSE,			/* pc_relative */
7573d8817e4Smiod 	 0,			/* bitpos */
7583d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
7593d8817e4Smiod 	 0,			/* special_function */
7603d8817e4Smiod 	 "R_RL",		/* name */
7613d8817e4Smiod 	 TRUE,			/* partial_inplace */
7623d8817e4Smiod 	 0xffff,		/* src_mask */
7633d8817e4Smiod 	 0xffff,		/* dst_mask */
7643d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7653d8817e4Smiod 
7663d8817e4Smiod   /* Load address.  */
7673d8817e4Smiod   HOWTO (R_RLA,			/* type */
7683d8817e4Smiod 	 0,			/* rightshift */
7693d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
7703d8817e4Smiod 	 16,			/* bitsize */
7713d8817e4Smiod 	 FALSE,			/* pc_relative */
7723d8817e4Smiod 	 0,			/* bitpos */
7733d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
7743d8817e4Smiod 	 0,			/* special_function */
7753d8817e4Smiod 	 "R_RLA",		/* name */
7763d8817e4Smiod 	 TRUE,			/* partial_inplace */
7773d8817e4Smiod 	 0xffff,		/* src_mask */
7783d8817e4Smiod 	 0xffff,		/* dst_mask */
7793d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7803d8817e4Smiod 
7813d8817e4Smiod   EMPTY_HOWTO (0xe),
7823d8817e4Smiod 
7833d8817e4Smiod   /* Non-relocating reference.  */
7843d8817e4Smiod   HOWTO (R_REF,			/* type */
7853d8817e4Smiod 	 0,			/* rightshift */
7863d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
7873d8817e4Smiod 	 32,			/* bitsize */
7883d8817e4Smiod 	 FALSE,			/* pc_relative */
7893d8817e4Smiod 	 0,			/* bitpos */
7903d8817e4Smiod 	 complain_overflow_dont, /* complain_on_overflow */
7913d8817e4Smiod 	 0,			/* special_function */
7923d8817e4Smiod 	 "R_REF",		/* name */
7933d8817e4Smiod 	 FALSE,			/* partial_inplace */
7943d8817e4Smiod 	 0,			/* src_mask */
7953d8817e4Smiod 	 0,			/* dst_mask */
7963d8817e4Smiod 	 FALSE),		/* pcrel_offset */
7973d8817e4Smiod 
7983d8817e4Smiod   EMPTY_HOWTO (0x10),
7993d8817e4Smiod   EMPTY_HOWTO (0x11),
8003d8817e4Smiod 
8013d8817e4Smiod   /* TOC relative indirect load.  */
8023d8817e4Smiod   HOWTO (R_TRL,			/* type */
8033d8817e4Smiod 	 0,			/* rightshift */
8043d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
8053d8817e4Smiod 	 16,			/* bitsize */
8063d8817e4Smiod 	 FALSE,			/* pc_relative */
8073d8817e4Smiod 	 0,			/* bitpos */
8083d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8093d8817e4Smiod 	 0,			/* special_function */
8103d8817e4Smiod 	 "R_TRL",		/* name */
8113d8817e4Smiod 	 TRUE,			/* partial_inplace */
8123d8817e4Smiod 	 0xffff,		/* src_mask */
8133d8817e4Smiod 	 0xffff,		/* dst_mask */
8143d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8153d8817e4Smiod 
8163d8817e4Smiod   /* TOC relative load address.  */
8173d8817e4Smiod   HOWTO (R_TRLA,		/* type */
8183d8817e4Smiod 	 0,			/* rightshift */
8193d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
8203d8817e4Smiod 	 16,			/* bitsize */
8213d8817e4Smiod 	 FALSE,			/* pc_relative */
8223d8817e4Smiod 	 0,			/* bitpos */
8233d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8243d8817e4Smiod 	 0,			/* special_function */
8253d8817e4Smiod 	 "R_TRLA",		/* name */
8263d8817e4Smiod 	 TRUE,			/* partial_inplace */
8273d8817e4Smiod 	 0xffff,		/* src_mask */
8283d8817e4Smiod 	 0xffff,		/* dst_mask */
8293d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8303d8817e4Smiod 
8313d8817e4Smiod   /* Modifiable relative branch.  */
8323d8817e4Smiod   HOWTO (R_RRTBI,		 /* type */
8333d8817e4Smiod 	 1,			/* rightshift */
8343d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
8353d8817e4Smiod 	 32,			/* bitsize */
8363d8817e4Smiod 	 FALSE,			/* pc_relative */
8373d8817e4Smiod 	 0,			/* bitpos */
8383d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8393d8817e4Smiod 	 0,			/* special_function */
8403d8817e4Smiod 	 "R_RRTBI",		/* name */
8413d8817e4Smiod 	 TRUE,			/* partial_inplace */
8423d8817e4Smiod 	 0xffffffff,		/* src_mask */
8433d8817e4Smiod 	 0xffffffff,		/* dst_mask */
8443d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8453d8817e4Smiod 
8463d8817e4Smiod   /* Modifiable absolute branch.  */
8473d8817e4Smiod   HOWTO (R_RRTBA,		 /* type */
8483d8817e4Smiod 	 1,			/* rightshift */
8493d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
8503d8817e4Smiod 	 32,			/* bitsize */
8513d8817e4Smiod 	 FALSE,			/* pc_relative */
8523d8817e4Smiod 	 0,			/* bitpos */
8533d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8543d8817e4Smiod 	 0,			/* special_function */
8553d8817e4Smiod 	 "R_RRTBA",		/* name */
8563d8817e4Smiod 	 TRUE,			/* partial_inplace */
8573d8817e4Smiod 	 0xffffffff,		/* src_mask */
8583d8817e4Smiod 	 0xffffffff,		/* dst_mask */
8593d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8603d8817e4Smiod 
8613d8817e4Smiod   /* Modifiable call absolute indirect.  */
8623d8817e4Smiod   HOWTO (R_CAI,			/* type */
8633d8817e4Smiod 	 0,			/* rightshift */
8643d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
8653d8817e4Smiod 	 16,			/* bitsize */
8663d8817e4Smiod 	 FALSE,			/* pc_relative */
8673d8817e4Smiod 	 0,			/* bitpos */
8683d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8693d8817e4Smiod 	 0,			/* special_function */
8703d8817e4Smiod 	 "R_CAI",		/* name */
8713d8817e4Smiod 	 TRUE,			/* partial_inplace */
8723d8817e4Smiod 	 0xffff,		/* src_mask */
8733d8817e4Smiod 	 0xffff,		/* dst_mask */
8743d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8753d8817e4Smiod 
8763d8817e4Smiod   /* Modifiable call relative.  */
8773d8817e4Smiod   HOWTO (R_CREL,		/* type */
8783d8817e4Smiod 	 0,			/* rightshift */
8793d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
8803d8817e4Smiod 	 16,			/* bitsize */
8813d8817e4Smiod 	 FALSE,			/* pc_relative */
8823d8817e4Smiod 	 0,			/* bitpos */
8833d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8843d8817e4Smiod 	 0,			/* special_function */
8853d8817e4Smiod 	 "R_CREL",		/* name */
8863d8817e4Smiod 	 TRUE,			/* partial_inplace */
8873d8817e4Smiod 	 0xffff,		/* src_mask */
8883d8817e4Smiod 	 0xffff,		/* dst_mask */
8893d8817e4Smiod 	 FALSE),		/* pcrel_offset */
8903d8817e4Smiod 
8913d8817e4Smiod   /* Modifiable branch absolute.  */
8923d8817e4Smiod   HOWTO (R_RBA,			/* type */
8933d8817e4Smiod 	 0,			/* rightshift */
8943d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
8953d8817e4Smiod 	 26,			/* bitsize */
8963d8817e4Smiod 	 FALSE,			/* pc_relative */
8973d8817e4Smiod 	 0,			/* bitpos */
8983d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
8993d8817e4Smiod 	 0,			/* special_function */
9003d8817e4Smiod 	 "R_RBA",		/* name */
9013d8817e4Smiod 	 TRUE,			/* partial_inplace */
9023d8817e4Smiod 	 0x03fffffc,		/* src_mask */
9033d8817e4Smiod 	 0x03fffffc,		/* dst_mask */
9043d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9053d8817e4Smiod 
9063d8817e4Smiod   /* Modifiable branch absolute.  */
9073d8817e4Smiod   HOWTO (R_RBAC,		/* type */
9083d8817e4Smiod 	 0,			/* rightshift */
9093d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
9103d8817e4Smiod 	 32,			/* bitsize */
9113d8817e4Smiod 	 FALSE,			/* pc_relative */
9123d8817e4Smiod 	 0,			/* bitpos */
9133d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
9143d8817e4Smiod 	 0,			/* special_function */
9153d8817e4Smiod 	 "R_RBAC",		/* name */
9163d8817e4Smiod 	 TRUE,			/* partial_inplace */
9173d8817e4Smiod 	 0xffffffff,		/* src_mask */
9183d8817e4Smiod 	 0xffffffff,		/* dst_mask */
9193d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9203d8817e4Smiod 
9213d8817e4Smiod   /* Modifiable branch relative.  */
9223d8817e4Smiod   HOWTO (R_RBR,			/* type */
9233d8817e4Smiod 	 0,			/* rightshift */
9243d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
9253d8817e4Smiod 	 26,			/* bitsize */
9263d8817e4Smiod 	 FALSE,			/* pc_relative */
9273d8817e4Smiod 	 0,			/* bitpos */
9283d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
9293d8817e4Smiod 	 0,			/* special_function */
9303d8817e4Smiod 	 "R_RBR_26",		/* name */
9313d8817e4Smiod 	 TRUE,			/* partial_inplace */
9323d8817e4Smiod 	 0x03fffffc,		/* src_mask */
9333d8817e4Smiod 	 0x03fffffc,		/* dst_mask */
9343d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9353d8817e4Smiod 
9363d8817e4Smiod   /* Modifiable branch absolute.  */
9373d8817e4Smiod   HOWTO (R_RBRC,		/* type */
9383d8817e4Smiod 	 0,			/* rightshift */
9393d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
9403d8817e4Smiod 	 16,			/* bitsize */
9413d8817e4Smiod 	 FALSE,			/* pc_relative */
9423d8817e4Smiod 	 0,			/* bitpos */
9433d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
9443d8817e4Smiod 	 0,			/* special_function */
9453d8817e4Smiod 	 "R_RBRC",		/* name */
9463d8817e4Smiod 	 TRUE,			/* partial_inplace */
9473d8817e4Smiod 	 0xffff,		/* src_mask */
9483d8817e4Smiod 	 0xffff,		/* dst_mask */
9493d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9503d8817e4Smiod 
9513d8817e4Smiod   /* 16 bit Non modifiable absolute branch.  */
9523d8817e4Smiod   HOWTO (R_BA,			/* type */
9533d8817e4Smiod 	 0,			/* rightshift */
9543d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
9553d8817e4Smiod 	 16,			/* bitsize */
9563d8817e4Smiod 	 FALSE,			/* pc_relative */
9573d8817e4Smiod 	 0,			/* bitpos */
9583d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
9593d8817e4Smiod 	 0,			/* special_function */
9603d8817e4Smiod 	 "R_BA_16",		/* name */
9613d8817e4Smiod 	 TRUE,			/* partial_inplace */
9623d8817e4Smiod 	 0xfffc,		/* src_mask */
9633d8817e4Smiod 	 0xfffc,		/* dst_mask */
9643d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9653d8817e4Smiod 
9663d8817e4Smiod   /* Modifiable branch relative.  */
9673d8817e4Smiod   HOWTO (R_RBR,			/* type */
9683d8817e4Smiod 	 0,			/* rightshift */
9693d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
9703d8817e4Smiod 	 16,			/* bitsize */
9713d8817e4Smiod 	 FALSE,			/* pc_relative */
9723d8817e4Smiod 	 0,			/* bitpos */
9733d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
9743d8817e4Smiod 	 0,			/* special_function */
9753d8817e4Smiod 	 "R_RBR_16",		/* name */
9763d8817e4Smiod 	 TRUE,			/* partial_inplace */
9773d8817e4Smiod 	 0xffff,		/* src_mask */
9783d8817e4Smiod 	 0xffff,		/* dst_mask */
9793d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9803d8817e4Smiod 
9813d8817e4Smiod   /* Modifiable branch relative.  */
9823d8817e4Smiod   HOWTO (R_RBA,			/* type */
9833d8817e4Smiod 	 0,			/* rightshift */
9843d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
9853d8817e4Smiod 	 16,			/* bitsize */
9863d8817e4Smiod 	 FALSE,			/* pc_relative */
9873d8817e4Smiod 	 0,			/* bitpos */
9883d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
9893d8817e4Smiod 	 0,			/* special_function */
9903d8817e4Smiod 	 "R_RBA_16",		/* name */
9913d8817e4Smiod 	 TRUE,			/* partial_inplace */
9923d8817e4Smiod 	 0xffff,		/* src_mask */
9933d8817e4Smiod 	 0xffff,		/* dst_mask */
9943d8817e4Smiod 	 FALSE),		/* pcrel_offset */
9953d8817e4Smiod 
9963d8817e4Smiod };
9973d8817e4Smiod 
9983d8817e4Smiod void
xcoff_rtype2howto(relent,internal)9993d8817e4Smiod xcoff_rtype2howto (relent, internal)
10003d8817e4Smiod      arelent *relent;
10013d8817e4Smiod      struct internal_reloc *internal;
10023d8817e4Smiod {
10033d8817e4Smiod   if (internal->r_type > R_RBRC)
10043d8817e4Smiod     abort ();
10053d8817e4Smiod 
10063d8817e4Smiod   /* Default howto layout works most of the time */
10073d8817e4Smiod   relent->howto = &xcoff_howto_table[internal->r_type];
10083d8817e4Smiod 
10093d8817e4Smiod   /* Special case some 16 bit reloc */
10103d8817e4Smiod   if (15 == (internal->r_size & 0x1f))
10113d8817e4Smiod     {
10123d8817e4Smiod       if (R_BA == internal->r_type)
10133d8817e4Smiod 	relent->howto = &xcoff_howto_table[0x1c];
10143d8817e4Smiod       else if (R_RBR == internal->r_type)
10153d8817e4Smiod 	relent->howto = &xcoff_howto_table[0x1d];
10163d8817e4Smiod       else if (R_RBA == internal->r_type)
10173d8817e4Smiod 	relent->howto = &xcoff_howto_table[0x1e];
10183d8817e4Smiod     }
10193d8817e4Smiod 
10203d8817e4Smiod   /* The r_size field of an XCOFF reloc encodes the bitsize of the
10213d8817e4Smiod      relocation, as well as indicating whether it is signed or not.
10223d8817e4Smiod      Doublecheck that the relocation information gathered from the
10233d8817e4Smiod      type matches this information.  The bitsize is not significant
10243d8817e4Smiod      for R_REF relocs.  */
10253d8817e4Smiod   if (relent->howto->dst_mask != 0
10263d8817e4Smiod       && (relent->howto->bitsize
10273d8817e4Smiod 	  != ((unsigned int) internal->r_size & 0x1f) + 1))
10283d8817e4Smiod     abort ();
10293d8817e4Smiod }
10303d8817e4Smiod 
10313d8817e4Smiod reloc_howto_type *
_bfd_xcoff_reloc_type_lookup(abfd,code)10323d8817e4Smiod _bfd_xcoff_reloc_type_lookup (abfd, code)
10333d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
10343d8817e4Smiod      bfd_reloc_code_real_type code;
10353d8817e4Smiod {
10363d8817e4Smiod   switch (code)
10373d8817e4Smiod     {
10383d8817e4Smiod     case BFD_RELOC_PPC_B26:
10393d8817e4Smiod       return &xcoff_howto_table[0xa];
10403d8817e4Smiod     case BFD_RELOC_PPC_BA16:
10413d8817e4Smiod       return &xcoff_howto_table[0x1c];
10423d8817e4Smiod     case BFD_RELOC_PPC_BA26:
10433d8817e4Smiod       return &xcoff_howto_table[8];
10443d8817e4Smiod     case BFD_RELOC_PPC_TOC16:
10453d8817e4Smiod       return &xcoff_howto_table[3];
10463d8817e4Smiod     case BFD_RELOC_32:
10473d8817e4Smiod     case BFD_RELOC_CTOR:
10483d8817e4Smiod       return &xcoff_howto_table[0];
10493d8817e4Smiod     default:
10503d8817e4Smiod       return NULL;
10513d8817e4Smiod     }
10523d8817e4Smiod }
10533d8817e4Smiod 
10543d8817e4Smiod 
10553d8817e4Smiod /* XCOFF archive support.  The original version of this code was by
10563d8817e4Smiod    Damon A. Permezel.  It was enhanced to permit cross support, and
10573d8817e4Smiod    writing archive files, by Ian Lance Taylor, Cygnus Support.
10583d8817e4Smiod 
10593d8817e4Smiod    XCOFF uses its own archive format.  Everything is hooked together
10603d8817e4Smiod    with file offset links, so it is possible to rapidly update an
10613d8817e4Smiod    archive in place.  Of course, we don't do that.  An XCOFF archive
10623d8817e4Smiod    has a real file header, not just an ARMAG string.  The structure of
10633d8817e4Smiod    the file header and of each archive header appear below.
10643d8817e4Smiod 
10653d8817e4Smiod    An XCOFF archive also has a member table, which is a list of
10663d8817e4Smiod    elements in the archive (you can get that by looking through the
10673d8817e4Smiod    linked list, but you have to read a lot more of the file).  The
10683d8817e4Smiod    member table has a normal archive header with an empty name.  It is
10693d8817e4Smiod    normally (and perhaps must be) the second to last entry in the
10703d8817e4Smiod    archive.  The member table data is almost printable ASCII.  It
10713d8817e4Smiod    starts with a 12 character decimal string which is the number of
10723d8817e4Smiod    entries in the table.  For each entry it has a 12 character decimal
10733d8817e4Smiod    string which is the offset in the archive of that member.  These
10743d8817e4Smiod    entries are followed by a series of null terminated strings which
10753d8817e4Smiod    are the member names for each entry.
10763d8817e4Smiod 
10773d8817e4Smiod    Finally, an XCOFF archive has a global symbol table, which is what
10783d8817e4Smiod    we call the armap.  The global symbol table has a normal archive
10793d8817e4Smiod    header with an empty name.  It is normally (and perhaps must be)
10803d8817e4Smiod    the last entry in the archive.  The contents start with a four byte
10813d8817e4Smiod    binary number which is the number of entries.  This is followed by
10823d8817e4Smiod    a that many four byte binary numbers; each is the file offset of an
10833d8817e4Smiod    entry in the archive.  These numbers are followed by a series of
10843d8817e4Smiod    null terminated strings, which are symbol names.
10853d8817e4Smiod 
10863d8817e4Smiod    AIX 4.3 introduced a new archive format which can handle larger
10873d8817e4Smiod    files and also 32- and 64-bit objects in the same archive.  The
10883d8817e4Smiod    things said above remain true except that there is now more than
10893d8817e4Smiod    one global symbol table.  The one is used to index 32-bit objects,
10903d8817e4Smiod    the other for 64-bit objects.
10913d8817e4Smiod 
10923d8817e4Smiod    The new archives (recognizable by the new ARMAG string) has larger
10933d8817e4Smiod    field lengths so that we cannot really share any code.  Also we have
10943d8817e4Smiod    to take care that we are not generating the new form of archives
10953d8817e4Smiod    on AIX 4.2 or earlier systems.  */
10963d8817e4Smiod 
10973d8817e4Smiod /* XCOFF archives use this as a magic string.  Note that both strings
10983d8817e4Smiod    have the same length.  */
10993d8817e4Smiod 
11003d8817e4Smiod /* Set the magic for archive.  */
11013d8817e4Smiod 
11023d8817e4Smiod bfd_boolean
bfd_xcoff_ar_archive_set_magic(abfd,magic)11033d8817e4Smiod bfd_xcoff_ar_archive_set_magic (abfd, magic)
11043d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
11053d8817e4Smiod      char *magic ATTRIBUTE_UNUSED;
11063d8817e4Smiod {
11073d8817e4Smiod   /* Not supported yet.  */
11083d8817e4Smiod   return FALSE;
11093d8817e4Smiod  /* bfd_xcoff_archive_set_magic (abfd, magic); */
11103d8817e4Smiod }
11113d8817e4Smiod 
11123d8817e4Smiod /* Read in the armap of an XCOFF archive.  */
11133d8817e4Smiod 
11143d8817e4Smiod bfd_boolean
_bfd_xcoff_slurp_armap(abfd)11153d8817e4Smiod _bfd_xcoff_slurp_armap (abfd)
11163d8817e4Smiod      bfd *abfd;
11173d8817e4Smiod {
11183d8817e4Smiod   file_ptr off;
11193d8817e4Smiod   size_t namlen;
11203d8817e4Smiod   bfd_size_type sz;
11213d8817e4Smiod   bfd_byte *contents, *cend;
11223d8817e4Smiod   bfd_vma c, i;
11233d8817e4Smiod   carsym *arsym;
11243d8817e4Smiod   bfd_byte *p;
11253d8817e4Smiod 
11263d8817e4Smiod   if (xcoff_ardata (abfd) == NULL)
11273d8817e4Smiod     {
11283d8817e4Smiod       bfd_has_map (abfd) = FALSE;
11293d8817e4Smiod       return TRUE;
11303d8817e4Smiod     }
11313d8817e4Smiod 
11323d8817e4Smiod   if (! xcoff_big_format_p (abfd))
11333d8817e4Smiod     {
11343d8817e4Smiod       /* This is for the old format.  */
11353d8817e4Smiod       struct xcoff_ar_hdr hdr;
11363d8817e4Smiod 
11373d8817e4Smiod       off = strtol (xcoff_ardata (abfd)->symoff, (char **) NULL, 10);
11383d8817e4Smiod       if (off == 0)
11393d8817e4Smiod 	{
11403d8817e4Smiod 	  bfd_has_map (abfd) = FALSE;
11413d8817e4Smiod 	  return TRUE;
11423d8817e4Smiod 	}
11433d8817e4Smiod 
11443d8817e4Smiod       if (bfd_seek (abfd, off, SEEK_SET) != 0)
11453d8817e4Smiod 	return FALSE;
11463d8817e4Smiod 
11473d8817e4Smiod       /* The symbol table starts with a normal archive header.  */
11483d8817e4Smiod       if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd)
11493d8817e4Smiod 	  != SIZEOF_AR_HDR)
11503d8817e4Smiod 	return FALSE;
11513d8817e4Smiod 
11523d8817e4Smiod       /* Skip the name (normally empty).  */
11533d8817e4Smiod       namlen = strtol (hdr.namlen, (char **) NULL, 10);
11543d8817e4Smiod       off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG;
11553d8817e4Smiod       if (bfd_seek (abfd, off, SEEK_CUR) != 0)
11563d8817e4Smiod 	return FALSE;
11573d8817e4Smiod 
11583d8817e4Smiod       sz = strtol (hdr.size, (char **) NULL, 10);
11593d8817e4Smiod 
11603d8817e4Smiod       /* Read in the entire symbol table.  */
11613d8817e4Smiod       contents = (bfd_byte *) bfd_alloc (abfd, sz);
11623d8817e4Smiod       if (contents == NULL)
11633d8817e4Smiod 	return FALSE;
11643d8817e4Smiod       if (bfd_bread ((PTR) contents, sz, abfd) != sz)
11653d8817e4Smiod 	return FALSE;
11663d8817e4Smiod 
11673d8817e4Smiod       /* The symbol table starts with a four byte count.  */
11683d8817e4Smiod       c = H_GET_32 (abfd, contents);
11693d8817e4Smiod 
11703d8817e4Smiod       if (c * 4 >= sz)
11713d8817e4Smiod 	{
11723d8817e4Smiod 	  bfd_set_error (bfd_error_bad_value);
11733d8817e4Smiod 	  return FALSE;
11743d8817e4Smiod 	}
11753d8817e4Smiod 
11763d8817e4Smiod       bfd_ardata (abfd)->symdefs =
11773d8817e4Smiod 	((carsym *) bfd_alloc (abfd, c * sizeof (carsym)));
11783d8817e4Smiod       if (bfd_ardata (abfd)->symdefs == NULL)
11793d8817e4Smiod 	return FALSE;
11803d8817e4Smiod 
11813d8817e4Smiod       /* After the count comes a list of four byte file offsets.  */
11823d8817e4Smiod       for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 4;
11833d8817e4Smiod 	   i < c;
11843d8817e4Smiod 	   ++i, ++arsym, p += 4)
11853d8817e4Smiod 	arsym->file_offset = H_GET_32 (abfd, p);
11863d8817e4Smiod     }
11873d8817e4Smiod   else
11883d8817e4Smiod     {
11893d8817e4Smiod       /* This is for the new format.  */
11903d8817e4Smiod       struct xcoff_ar_hdr_big hdr;
11913d8817e4Smiod 
11923d8817e4Smiod       off = strtol (xcoff_ardata_big (abfd)->symoff, (char **) NULL, 10);
11933d8817e4Smiod       if (off == 0)
11943d8817e4Smiod 	{
11953d8817e4Smiod 	  bfd_has_map (abfd) = FALSE;
11963d8817e4Smiod 	  return TRUE;
11973d8817e4Smiod 	}
11983d8817e4Smiod 
11993d8817e4Smiod       if (bfd_seek (abfd, off, SEEK_SET) != 0)
12003d8817e4Smiod 	return FALSE;
12013d8817e4Smiod 
12023d8817e4Smiod       /* The symbol table starts with a normal archive header.  */
12033d8817e4Smiod       if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
12043d8817e4Smiod 	  != SIZEOF_AR_HDR_BIG)
12053d8817e4Smiod 	return FALSE;
12063d8817e4Smiod 
12073d8817e4Smiod       /* Skip the name (normally empty).  */
12083d8817e4Smiod       namlen = strtol (hdr.namlen, (char **) NULL, 10);
12093d8817e4Smiod       off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG;
12103d8817e4Smiod       if (bfd_seek (abfd, off, SEEK_CUR) != 0)
12113d8817e4Smiod 	return FALSE;
12123d8817e4Smiod 
12133d8817e4Smiod       /* XXX This actually has to be a call to strtoll (at least on 32-bit
12143d8817e4Smiod 	 machines) since the field width is 20 and there numbers with more
12153d8817e4Smiod 	 than 32 bits can be represented.  */
12163d8817e4Smiod       sz = strtol (hdr.size, (char **) NULL, 10);
12173d8817e4Smiod 
12183d8817e4Smiod       /* Read in the entire symbol table.  */
12193d8817e4Smiod       contents = (bfd_byte *) bfd_alloc (abfd, sz);
12203d8817e4Smiod       if (contents == NULL)
12213d8817e4Smiod 	return FALSE;
12223d8817e4Smiod       if (bfd_bread ((PTR) contents, sz, abfd) != sz)
12233d8817e4Smiod 	return FALSE;
12243d8817e4Smiod 
12253d8817e4Smiod       /* The symbol table starts with an eight byte count.  */
12263d8817e4Smiod       c = H_GET_64 (abfd, contents);
12273d8817e4Smiod 
12283d8817e4Smiod       if (c * 8 >= sz)
12293d8817e4Smiod 	{
12303d8817e4Smiod 	  bfd_set_error (bfd_error_bad_value);
12313d8817e4Smiod 	  return FALSE;
12323d8817e4Smiod 	}
12333d8817e4Smiod 
12343d8817e4Smiod       bfd_ardata (abfd)->symdefs =
12353d8817e4Smiod 	((carsym *) bfd_alloc (abfd, c * sizeof (carsym)));
12363d8817e4Smiod       if (bfd_ardata (abfd)->symdefs == NULL)
12373d8817e4Smiod 	return FALSE;
12383d8817e4Smiod 
12393d8817e4Smiod       /* After the count comes a list of eight byte file offsets.  */
12403d8817e4Smiod       for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8;
12413d8817e4Smiod 	   i < c;
12423d8817e4Smiod 	   ++i, ++arsym, p += 8)
12433d8817e4Smiod 	arsym->file_offset = H_GET_64 (abfd, p);
12443d8817e4Smiod     }
12453d8817e4Smiod 
12463d8817e4Smiod   /* After the file offsets come null terminated symbol names.  */
12473d8817e4Smiod   cend = contents + sz;
12483d8817e4Smiod   for (i = 0, arsym = bfd_ardata (abfd)->symdefs;
12493d8817e4Smiod        i < c;
12503d8817e4Smiod        ++i, ++arsym, p += strlen ((char *) p) + 1)
12513d8817e4Smiod     {
12523d8817e4Smiod       if (p >= cend)
12533d8817e4Smiod 	{
12543d8817e4Smiod 	  bfd_set_error (bfd_error_bad_value);
12553d8817e4Smiod 	  return FALSE;
12563d8817e4Smiod 	}
12573d8817e4Smiod       arsym->name = (char *) p;
12583d8817e4Smiod     }
12593d8817e4Smiod 
12603d8817e4Smiod   bfd_ardata (abfd)->symdef_count = c;
12613d8817e4Smiod   bfd_has_map (abfd) = TRUE;
12623d8817e4Smiod 
12633d8817e4Smiod   return TRUE;
12643d8817e4Smiod }
12653d8817e4Smiod 
12663d8817e4Smiod /* See if this is an XCOFF archive.  */
12673d8817e4Smiod 
12683d8817e4Smiod const bfd_target *
_bfd_xcoff_archive_p(abfd)12693d8817e4Smiod _bfd_xcoff_archive_p (abfd)
12703d8817e4Smiod      bfd *abfd;
12713d8817e4Smiod {
12723d8817e4Smiod   struct artdata *tdata_hold;
12733d8817e4Smiod   char magic[SXCOFFARMAG];
12743d8817e4Smiod   bfd_size_type amt = SXCOFFARMAG;
12753d8817e4Smiod 
12763d8817e4Smiod   if (bfd_bread ((PTR) magic, amt, abfd) != amt)
12773d8817e4Smiod     {
12783d8817e4Smiod       if (bfd_get_error () != bfd_error_system_call)
12793d8817e4Smiod 	bfd_set_error (bfd_error_wrong_format);
12803d8817e4Smiod       return NULL;
12813d8817e4Smiod     }
12823d8817e4Smiod 
12833d8817e4Smiod   if (strncmp (magic, XCOFFARMAG, SXCOFFARMAG) != 0
12843d8817e4Smiod       && strncmp (magic, XCOFFARMAGBIG, SXCOFFARMAG) != 0)
12853d8817e4Smiod     {
12863d8817e4Smiod       bfd_set_error (bfd_error_wrong_format);
12873d8817e4Smiod       return NULL;
12883d8817e4Smiod     }
12893d8817e4Smiod 
12903d8817e4Smiod   tdata_hold = bfd_ardata (abfd);
12913d8817e4Smiod 
12923d8817e4Smiod   amt = sizeof (struct artdata);
12933d8817e4Smiod   bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt);
12943d8817e4Smiod   if (bfd_ardata (abfd) == (struct artdata *) NULL)
12953d8817e4Smiod     goto error_ret_restore;
12963d8817e4Smiod 
12973d8817e4Smiod   /* Cleared by bfd_zalloc above.
12983d8817e4Smiod      bfd_ardata (abfd)->cache = NULL;
12993d8817e4Smiod      bfd_ardata (abfd)->archive_head = NULL;
13003d8817e4Smiod      bfd_ardata (abfd)->symdefs = NULL;
13013d8817e4Smiod      bfd_ardata (abfd)->extended_names = NULL;
13023d8817e4Smiod      bfd_ardata (abfd)->extended_names_size = 0;  */
13033d8817e4Smiod 
13043d8817e4Smiod   /* Now handle the two formats.  */
13053d8817e4Smiod   if (magic[1] != 'b')
13063d8817e4Smiod     {
13073d8817e4Smiod       /* This is the old format.  */
13083d8817e4Smiod       struct xcoff_ar_file_hdr hdr;
13093d8817e4Smiod 
13103d8817e4Smiod       /* Copy over the magic string.  */
13113d8817e4Smiod       memcpy (hdr.magic, magic, SXCOFFARMAG);
13123d8817e4Smiod 
13133d8817e4Smiod       /* Now read the rest of the file header.  */
13143d8817e4Smiod       amt = SIZEOF_AR_FILE_HDR - SXCOFFARMAG;
13153d8817e4Smiod       if (bfd_bread ((PTR) &hdr.memoff, amt, abfd) != amt)
13163d8817e4Smiod 	{
13173d8817e4Smiod 	  if (bfd_get_error () != bfd_error_system_call)
13183d8817e4Smiod 	    bfd_set_error (bfd_error_wrong_format);
13193d8817e4Smiod 	  goto error_ret;
13203d8817e4Smiod 	}
13213d8817e4Smiod 
13223d8817e4Smiod       bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
13233d8817e4Smiod 						      (char **) NULL, 10);
13243d8817e4Smiod 
13253d8817e4Smiod       amt = SIZEOF_AR_FILE_HDR;
13263d8817e4Smiod       bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt);
13273d8817e4Smiod       if (bfd_ardata (abfd)->tdata == NULL)
13283d8817e4Smiod 	goto error_ret;
13293d8817e4Smiod 
13303d8817e4Smiod       memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR);
13313d8817e4Smiod     }
13323d8817e4Smiod   else
13333d8817e4Smiod     {
13343d8817e4Smiod       /* This is the new format.  */
13353d8817e4Smiod       struct xcoff_ar_file_hdr_big hdr;
13363d8817e4Smiod 
13373d8817e4Smiod       /* Copy over the magic string.  */
13383d8817e4Smiod       memcpy (hdr.magic, magic, SXCOFFARMAG);
13393d8817e4Smiod 
13403d8817e4Smiod       /* Now read the rest of the file header.  */
13413d8817e4Smiod       amt = SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG;
13423d8817e4Smiod       if (bfd_bread ((PTR) &hdr.memoff, amt, abfd) != amt)
13433d8817e4Smiod 	{
13443d8817e4Smiod 	  if (bfd_get_error () != bfd_error_system_call)
13453d8817e4Smiod 	    bfd_set_error (bfd_error_wrong_format);
13463d8817e4Smiod 	  goto error_ret;
13473d8817e4Smiod 	}
13483d8817e4Smiod 
13493d8817e4Smiod       bfd_ardata (abfd)->first_file_filepos = bfd_scan_vma (hdr.firstmemoff,
13503d8817e4Smiod 							    (const char **) 0,
13513d8817e4Smiod 							    10);
13523d8817e4Smiod 
13533d8817e4Smiod       amt = SIZEOF_AR_FILE_HDR_BIG;
13543d8817e4Smiod       bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt);
13553d8817e4Smiod       if (bfd_ardata (abfd)->tdata == NULL)
13563d8817e4Smiod 	goto error_ret;
13573d8817e4Smiod 
13583d8817e4Smiod       memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG);
13593d8817e4Smiod     }
13603d8817e4Smiod 
13613d8817e4Smiod   if (! _bfd_xcoff_slurp_armap (abfd))
13623d8817e4Smiod     {
13633d8817e4Smiod     error_ret:
13643d8817e4Smiod       bfd_release (abfd, bfd_ardata (abfd));
13653d8817e4Smiod     error_ret_restore:
13663d8817e4Smiod       bfd_ardata (abfd) = tdata_hold;
13673d8817e4Smiod       return NULL;
13683d8817e4Smiod     }
13693d8817e4Smiod 
13703d8817e4Smiod   return abfd->xvec;
13713d8817e4Smiod }
13723d8817e4Smiod 
13733d8817e4Smiod /* Read the archive header in an XCOFF archive.  */
13743d8817e4Smiod 
13753d8817e4Smiod PTR
_bfd_xcoff_read_ar_hdr(abfd)13763d8817e4Smiod _bfd_xcoff_read_ar_hdr (abfd)
13773d8817e4Smiod      bfd *abfd;
13783d8817e4Smiod {
13793d8817e4Smiod   bfd_size_type namlen;
13803d8817e4Smiod   struct areltdata *ret;
13813d8817e4Smiod   bfd_size_type amt = sizeof (struct areltdata);
13823d8817e4Smiod 
13833d8817e4Smiod   ret = (struct areltdata *) bfd_alloc (abfd, amt);
13843d8817e4Smiod   if (ret == NULL)
13853d8817e4Smiod     return NULL;
13863d8817e4Smiod 
13873d8817e4Smiod   if (! xcoff_big_format_p (abfd))
13883d8817e4Smiod     {
13893d8817e4Smiod       struct xcoff_ar_hdr hdr;
13903d8817e4Smiod       struct xcoff_ar_hdr *hdrp;
13913d8817e4Smiod 
13923d8817e4Smiod       if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd)
13933d8817e4Smiod 	  != SIZEOF_AR_HDR)
13943d8817e4Smiod 	{
13953d8817e4Smiod 	  free (ret);
13963d8817e4Smiod 	  return NULL;
13973d8817e4Smiod 	}
13983d8817e4Smiod 
13993d8817e4Smiod       namlen = strtol (hdr.namlen, (char **) NULL, 10);
14003d8817e4Smiod       amt = SIZEOF_AR_HDR + namlen + 1;
14013d8817e4Smiod       hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd, amt);
14023d8817e4Smiod       if (hdrp == NULL)
14033d8817e4Smiod 	{
14043d8817e4Smiod 	  free (ret);
14053d8817e4Smiod 	  return NULL;
14063d8817e4Smiod 	}
14073d8817e4Smiod       memcpy (hdrp, &hdr, SIZEOF_AR_HDR);
14083d8817e4Smiod       if (bfd_bread ((char *) hdrp + SIZEOF_AR_HDR, namlen, abfd) != namlen)
14093d8817e4Smiod 	{
14103d8817e4Smiod 	  free (ret);
14113d8817e4Smiod 	  return NULL;
14123d8817e4Smiod 	}
14133d8817e4Smiod       ((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0';
14143d8817e4Smiod 
14153d8817e4Smiod       ret->arch_header = (char *) hdrp;
14163d8817e4Smiod       ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
14173d8817e4Smiod       ret->filename = (char *) hdrp + SIZEOF_AR_HDR;
14183d8817e4Smiod     }
14193d8817e4Smiod   else
14203d8817e4Smiod     {
14213d8817e4Smiod       struct xcoff_ar_hdr_big hdr;
14223d8817e4Smiod       struct xcoff_ar_hdr_big *hdrp;
14233d8817e4Smiod 
14243d8817e4Smiod       if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
14253d8817e4Smiod 	  != SIZEOF_AR_HDR_BIG)
14263d8817e4Smiod 	{
14273d8817e4Smiod 	  free (ret);
14283d8817e4Smiod 	  return NULL;
14293d8817e4Smiod 	}
14303d8817e4Smiod 
14313d8817e4Smiod       namlen = strtol (hdr.namlen, (char **) NULL, 10);
14323d8817e4Smiod       amt = SIZEOF_AR_HDR_BIG + namlen + 1;
14333d8817e4Smiod       hdrp = (struct xcoff_ar_hdr_big *) bfd_alloc (abfd, amt);
14343d8817e4Smiod       if (hdrp == NULL)
14353d8817e4Smiod 	{
14363d8817e4Smiod 	  free (ret);
14373d8817e4Smiod 	  return NULL;
14383d8817e4Smiod 	}
14393d8817e4Smiod       memcpy (hdrp, &hdr, SIZEOF_AR_HDR_BIG);
14403d8817e4Smiod       if (bfd_bread ((char *) hdrp + SIZEOF_AR_HDR_BIG, namlen, abfd) != namlen)
14413d8817e4Smiod 	{
14423d8817e4Smiod 	  free (ret);
14433d8817e4Smiod 	  return NULL;
14443d8817e4Smiod 	}
14453d8817e4Smiod       ((char *) hdrp)[SIZEOF_AR_HDR_BIG + namlen] = '\0';
14463d8817e4Smiod 
14473d8817e4Smiod       ret->arch_header = (char *) hdrp;
14483d8817e4Smiod       /* XXX This actually has to be a call to strtoll (at least on 32-bit
14493d8817e4Smiod 	 machines) since the field width is 20 and there numbers with more
14503d8817e4Smiod 	 than 32 bits can be represented.  */
14513d8817e4Smiod       ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
14523d8817e4Smiod       ret->filename = (char *) hdrp + SIZEOF_AR_HDR_BIG;
14533d8817e4Smiod     }
14543d8817e4Smiod 
14553d8817e4Smiod   /* Skip over the XCOFFARFMAG at the end of the file name.  */
14563d8817e4Smiod   if (bfd_seek (abfd, (file_ptr) ((namlen & 1) + SXCOFFARFMAG), SEEK_CUR) != 0)
14573d8817e4Smiod     return NULL;
14583d8817e4Smiod 
14593d8817e4Smiod   return (PTR) ret;
14603d8817e4Smiod }
14613d8817e4Smiod 
14623d8817e4Smiod /* Open the next element in an XCOFF archive.  */
14633d8817e4Smiod 
14643d8817e4Smiod bfd *
_bfd_xcoff_openr_next_archived_file(archive,last_file)14653d8817e4Smiod _bfd_xcoff_openr_next_archived_file (archive, last_file)
14663d8817e4Smiod      bfd *archive;
14673d8817e4Smiod      bfd *last_file;
14683d8817e4Smiod {
14693d8817e4Smiod   file_ptr filestart;
14703d8817e4Smiod 
14713d8817e4Smiod   if (xcoff_ardata (archive) == NULL)
14723d8817e4Smiod     {
14733d8817e4Smiod       bfd_set_error (bfd_error_invalid_operation);
14743d8817e4Smiod       return NULL;
14753d8817e4Smiod     }
14763d8817e4Smiod 
14773d8817e4Smiod   if (! xcoff_big_format_p (archive))
14783d8817e4Smiod     {
14793d8817e4Smiod       if (last_file == NULL)
14803d8817e4Smiod 	filestart = bfd_ardata (archive)->first_file_filepos;
14813d8817e4Smiod       else
14823d8817e4Smiod 	filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL,
14833d8817e4Smiod 			    10);
14843d8817e4Smiod 
14853d8817e4Smiod       if (filestart == 0
14863d8817e4Smiod 	  || filestart == strtol (xcoff_ardata (archive)->memoff,
14873d8817e4Smiod 				  (char **) NULL, 10)
14883d8817e4Smiod 	  || filestart == strtol (xcoff_ardata (archive)->symoff,
14893d8817e4Smiod 				  (char **) NULL, 10))
14903d8817e4Smiod 	{
14913d8817e4Smiod 	  bfd_set_error (bfd_error_no_more_archived_files);
14923d8817e4Smiod 	  return NULL;
14933d8817e4Smiod 	}
14943d8817e4Smiod     }
14953d8817e4Smiod   else
14963d8817e4Smiod     {
14973d8817e4Smiod       if (last_file == NULL)
14983d8817e4Smiod 	filestart = bfd_ardata (archive)->first_file_filepos;
14993d8817e4Smiod       else
15003d8817e4Smiod 	/* XXX These actually have to be a calls to strtoll (at least
15013d8817e4Smiod 	   on 32-bit machines) since the fields's width is 20 and
15023d8817e4Smiod 	   there numbers with more than 32 bits can be represented.  */
15033d8817e4Smiod 	filestart = strtol (arch_xhdr_big (last_file)->nextoff, (char **) NULL,
15043d8817e4Smiod 			    10);
15053d8817e4Smiod 
15063d8817e4Smiod       /* XXX These actually have to be calls to strtoll (at least on 32-bit
15073d8817e4Smiod 	 machines) since the fields's width is 20 and there numbers with more
15083d8817e4Smiod 	 than 32 bits can be represented.  */
15093d8817e4Smiod       if (filestart == 0
15103d8817e4Smiod 	  || filestart == strtol (xcoff_ardata_big (archive)->memoff,
15113d8817e4Smiod 				  (char **) NULL, 10)
15123d8817e4Smiod 	  || filestart == strtol (xcoff_ardata_big (archive)->symoff,
15133d8817e4Smiod 				  (char **) NULL, 10))
15143d8817e4Smiod 	{
15153d8817e4Smiod 	  bfd_set_error (bfd_error_no_more_archived_files);
15163d8817e4Smiod 	  return NULL;
15173d8817e4Smiod 	}
15183d8817e4Smiod     }
15193d8817e4Smiod 
15203d8817e4Smiod   return _bfd_get_elt_at_filepos (archive, filestart);
15213d8817e4Smiod }
15223d8817e4Smiod 
15233d8817e4Smiod /* Stat an element in an XCOFF archive.  */
15243d8817e4Smiod 
15253d8817e4Smiod int
_bfd_xcoff_stat_arch_elt(abfd,s)15263d8817e4Smiod _bfd_xcoff_stat_arch_elt (abfd, s)
15273d8817e4Smiod      bfd *abfd;
15283d8817e4Smiod      struct stat *s;
15293d8817e4Smiod {
15303d8817e4Smiod   if (abfd->arelt_data == NULL)
15313d8817e4Smiod     {
15323d8817e4Smiod       bfd_set_error (bfd_error_invalid_operation);
15333d8817e4Smiod       return -1;
15343d8817e4Smiod     }
15353d8817e4Smiod 
15363d8817e4Smiod   if (! xcoff_big_format_p (abfd->my_archive))
15373d8817e4Smiod     {
15383d8817e4Smiod       struct xcoff_ar_hdr *hdrp = arch_xhdr (abfd);
15393d8817e4Smiod 
1540*d04417c8Smiod       s->st_mtime = strtoll (hdrp->date, (char **) NULL, 10);
15413d8817e4Smiod       s->st_uid = strtol (hdrp->uid, (char **) NULL, 10);
15423d8817e4Smiod       s->st_gid = strtol (hdrp->gid, (char **) NULL, 10);
15433d8817e4Smiod       s->st_mode = strtol (hdrp->mode, (char **) NULL, 8);
15443d8817e4Smiod       s->st_size = arch_eltdata (abfd)->parsed_size;
15453d8817e4Smiod     }
15463d8817e4Smiod   else
15473d8817e4Smiod     {
15483d8817e4Smiod       struct xcoff_ar_hdr_big *hdrp = arch_xhdr_big (abfd);
15493d8817e4Smiod 
1550*d04417c8Smiod       s->st_mtime = strtoll (hdrp->date, (char **) NULL, 10);
15513d8817e4Smiod       s->st_uid = strtol (hdrp->uid, (char **) NULL, 10);
15523d8817e4Smiod       s->st_gid = strtol (hdrp->gid, (char **) NULL, 10);
15533d8817e4Smiod       s->st_mode = strtol (hdrp->mode, (char **) NULL, 8);
15543d8817e4Smiod       s->st_size = arch_eltdata (abfd)->parsed_size;
15553d8817e4Smiod     }
15563d8817e4Smiod 
15573d8817e4Smiod   return 0;
15583d8817e4Smiod }
15593d8817e4Smiod 
15603d8817e4Smiod /* Normalize a file name for inclusion in an archive.  */
15613d8817e4Smiod 
15623d8817e4Smiod static const char *
normalize_filename(abfd)15633d8817e4Smiod normalize_filename (abfd)
15643d8817e4Smiod      bfd *abfd;
15653d8817e4Smiod {
15663d8817e4Smiod   const char *file;
15673d8817e4Smiod   const char *filename;
15683d8817e4Smiod 
15693d8817e4Smiod   file = bfd_get_filename (abfd);
15703d8817e4Smiod   filename = strrchr (file, '/');
15713d8817e4Smiod   if (filename != NULL)
15723d8817e4Smiod     filename++;
15733d8817e4Smiod   else
15743d8817e4Smiod     filename = file;
15753d8817e4Smiod   return filename;
15763d8817e4Smiod }
15773d8817e4Smiod 
15783d8817e4Smiod /* Write out an XCOFF armap.  */
15793d8817e4Smiod 
15803d8817e4Smiod static bfd_boolean
xcoff_write_armap_old(abfd,elength,map,orl_count,stridx)15813d8817e4Smiod xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
15823d8817e4Smiod      bfd *abfd;
15833d8817e4Smiod      unsigned int elength ATTRIBUTE_UNUSED;
15843d8817e4Smiod      struct orl *map;
15853d8817e4Smiod      unsigned int orl_count;
15863d8817e4Smiod      int stridx;
15873d8817e4Smiod {
15883d8817e4Smiod   struct xcoff_ar_hdr hdr;
15893d8817e4Smiod   char *p;
15903d8817e4Smiod   unsigned char buf[4];
15913d8817e4Smiod   bfd *sub;
15923d8817e4Smiod   file_ptr fileoff;
15933d8817e4Smiod   unsigned int i;
15943d8817e4Smiod 
15953d8817e4Smiod   memset (&hdr, 0, sizeof hdr);
15963d8817e4Smiod   sprintf (hdr.size, "%ld", (long) (4 + orl_count * 4 + stridx));
15973d8817e4Smiod   sprintf (hdr.nextoff, "%d", 0);
15983d8817e4Smiod   memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, XCOFFARMAG_ELEMENT_SIZE);
15993d8817e4Smiod   sprintf (hdr.date, "%d", 0);
16003d8817e4Smiod   sprintf (hdr.uid, "%d", 0);
16013d8817e4Smiod   sprintf (hdr.gid, "%d", 0);
16023d8817e4Smiod   sprintf (hdr.mode, "%d", 0);
16033d8817e4Smiod   sprintf (hdr.namlen, "%d", 0);
16043d8817e4Smiod 
16053d8817e4Smiod   /* We need spaces, not null bytes, in the header.  */
16063d8817e4Smiod   for (p = (char *) &hdr; p < (char *) &hdr + SIZEOF_AR_HDR; p++)
16073d8817e4Smiod     if (*p == '\0')
16083d8817e4Smiod       *p = ' ';
16093d8817e4Smiod 
16103d8817e4Smiod   if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd)
16113d8817e4Smiod       != SIZEOF_AR_HDR
16123d8817e4Smiod       || (bfd_bwrite (XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd)
16133d8817e4Smiod 	  != SXCOFFARFMAG))
16143d8817e4Smiod     return FALSE;
16153d8817e4Smiod 
16163d8817e4Smiod   H_PUT_32 (abfd, orl_count, buf);
16173d8817e4Smiod   if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
16183d8817e4Smiod     return FALSE;
16193d8817e4Smiod 
16203d8817e4Smiod   sub = abfd->archive_head;
16213d8817e4Smiod   fileoff = SIZEOF_AR_FILE_HDR;
16223d8817e4Smiod   i = 0;
16233d8817e4Smiod   while (sub != NULL && i < orl_count)
16243d8817e4Smiod     {
16253d8817e4Smiod       size_t namlen;
16263d8817e4Smiod 
16273d8817e4Smiod       while (map[i].u.abfd == sub)
16283d8817e4Smiod 	{
16293d8817e4Smiod 	  H_PUT_32 (abfd, fileoff, buf);
16303d8817e4Smiod 	  if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
16313d8817e4Smiod 	    return FALSE;
16323d8817e4Smiod 	  ++i;
16333d8817e4Smiod 	}
16343d8817e4Smiod       namlen = strlen (normalize_filename (sub));
16353d8817e4Smiod       namlen = (namlen + 1) &~ (size_t) 1;
16363d8817e4Smiod       fileoff += (SIZEOF_AR_HDR
16373d8817e4Smiod 		  + namlen
16383d8817e4Smiod 		  + SXCOFFARFMAG
16393d8817e4Smiod 		  + arelt_size (sub));
16403d8817e4Smiod       fileoff = (fileoff + 1) &~ 1;
16413d8817e4Smiod       sub = sub->next;
16423d8817e4Smiod     }
16433d8817e4Smiod 
16443d8817e4Smiod   for (i = 0; i < orl_count; i++)
16453d8817e4Smiod     {
16463d8817e4Smiod       const char *name;
16473d8817e4Smiod       size_t namlen;
16483d8817e4Smiod 
16493d8817e4Smiod       name = *map[i].name;
16503d8817e4Smiod       namlen = strlen (name);
16513d8817e4Smiod       if (bfd_bwrite (name, (bfd_size_type) (namlen + 1), abfd) != namlen + 1)
16523d8817e4Smiod 	return FALSE;
16533d8817e4Smiod     }
16543d8817e4Smiod 
16553d8817e4Smiod   if ((stridx & 1) != 0)
16563d8817e4Smiod     {
16573d8817e4Smiod       char b;
16583d8817e4Smiod 
16593d8817e4Smiod       b = '\0';
16603d8817e4Smiod       if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
16613d8817e4Smiod 	return FALSE;
16623d8817e4Smiod     }
16633d8817e4Smiod 
16643d8817e4Smiod   return TRUE;
16653d8817e4Smiod }
16663d8817e4Smiod 
16673d8817e4Smiod static char buff20[XCOFFARMAGBIG_ELEMENT_SIZE + 1];
16683d8817e4Smiod #define FMT20  "%-20lld"
16693d8817e4Smiod #define FMT12  "%-12d"
1670*d04417c8Smiod #define FMT12_LL  "%-12lld"
16713d8817e4Smiod #define FMT12_OCTAL  "%-12o"
16723d8817e4Smiod #define FMT4  "%-4d"
16733d8817e4Smiod #define PRINT20(d, v) \
16743d8817e4Smiod   sprintf (buff20, FMT20, (long long)(v)), \
16753d8817e4Smiod   memcpy ((void *) (d), buff20, 20)
16763d8817e4Smiod 
16773d8817e4Smiod #define PRINT12(d, v) \
16783d8817e4Smiod   sprintf (buff20, FMT12, (int)(v)), \
16793d8817e4Smiod   memcpy ((void *) (d), buff20, 12)
16803d8817e4Smiod 
1681*d04417c8Smiod #define PRINT12_LL(d, v) \
1682*d04417c8Smiod   sprintf (buff20, FMT12_LL, (long long)(v)), \
1683*d04417c8Smiod   memcpy ((void *) (d), buff20, 12)
1684*d04417c8Smiod 
16853d8817e4Smiod #define PRINT12_OCTAL(d, v) \
16863d8817e4Smiod   sprintf (buff20, FMT12_OCTAL, (unsigned int)(v)), \
16873d8817e4Smiod   memcpy ((void *) (d), buff20, 12)
16883d8817e4Smiod 
16893d8817e4Smiod #define PRINT4(d, v) \
16903d8817e4Smiod   sprintf (buff20, FMT4, (int)(v)), \
16913d8817e4Smiod   memcpy ((void *) (d), buff20, 4)
16923d8817e4Smiod 
16933d8817e4Smiod #define READ20(d, v) \
16943d8817e4Smiod   buff20[20] = 0, \
16953d8817e4Smiod   memcpy (buff20, (d), 20), \
16963d8817e4Smiod   (v) = bfd_scan_vma (buff20, (const char **) NULL, 10)
16973d8817e4Smiod 
16983d8817e4Smiod static bfd_boolean
do_pad(abfd,number)16993d8817e4Smiod do_pad (abfd, number)
17003d8817e4Smiod      bfd *abfd;
17013d8817e4Smiod      unsigned int number;
17023d8817e4Smiod {
17033d8817e4Smiod   bfd_byte b = 0;
17043d8817e4Smiod 
17053d8817e4Smiod   /* Limit pad to <= 4096.  */
17063d8817e4Smiod   if (number > 4096)
17073d8817e4Smiod     return FALSE;
17083d8817e4Smiod 
17093d8817e4Smiod   while (number--)
17103d8817e4Smiod     if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
17113d8817e4Smiod       return FALSE;
17123d8817e4Smiod 
17133d8817e4Smiod   return TRUE;
17143d8817e4Smiod }
17153d8817e4Smiod 
17163d8817e4Smiod static bfd_boolean
do_copy(out_bfd,in_bfd)17173d8817e4Smiod do_copy (out_bfd, in_bfd)
17183d8817e4Smiod      bfd *out_bfd;
17193d8817e4Smiod      bfd *in_bfd;
17203d8817e4Smiod {
17213d8817e4Smiod   bfd_size_type remaining;
17223d8817e4Smiod   bfd_byte buffer[DEFAULT_BUFFERSIZE];
17233d8817e4Smiod 
17243d8817e4Smiod   if (bfd_seek (in_bfd, (file_ptr) 0, SEEK_SET) != 0)
17253d8817e4Smiod     return FALSE;
17263d8817e4Smiod 
17273d8817e4Smiod   remaining = arelt_size (in_bfd);
17283d8817e4Smiod 
17293d8817e4Smiod   while (remaining >= DEFAULT_BUFFERSIZE)
17303d8817e4Smiod     {
17313d8817e4Smiod       if (bfd_bread (buffer, DEFAULT_BUFFERSIZE, in_bfd) != DEFAULT_BUFFERSIZE
17323d8817e4Smiod 	  || bfd_bwrite (buffer, DEFAULT_BUFFERSIZE, out_bfd) != DEFAULT_BUFFERSIZE)
17333d8817e4Smiod 	return FALSE;
17343d8817e4Smiod 
17353d8817e4Smiod       remaining -= DEFAULT_BUFFERSIZE;
17363d8817e4Smiod     }
17373d8817e4Smiod 
17383d8817e4Smiod   if (remaining)
17393d8817e4Smiod     {
17403d8817e4Smiod       if (bfd_bread (buffer, remaining, in_bfd) != remaining
17413d8817e4Smiod 	  || bfd_bwrite (buffer, remaining, out_bfd) != remaining)
17423d8817e4Smiod 	return FALSE;
17433d8817e4Smiod     }
17443d8817e4Smiod 
17453d8817e4Smiod   return TRUE;
17463d8817e4Smiod }
17473d8817e4Smiod 
17483d8817e4Smiod static bfd_boolean
do_shared_object_padding(out_bfd,in_bfd,offset,ar_header_size)17493d8817e4Smiod do_shared_object_padding (out_bfd, in_bfd, offset, ar_header_size)
17503d8817e4Smiod      bfd *out_bfd;
17513d8817e4Smiod      bfd *in_bfd;
17523d8817e4Smiod      file_ptr *offset;
17533d8817e4Smiod      int ar_header_size;
17543d8817e4Smiod {
17553d8817e4Smiod   if (bfd_check_format (in_bfd, bfd_object)
17563d8817e4Smiod       && bfd_get_flavour (in_bfd) == bfd_target_xcoff_flavour
17573d8817e4Smiod       && (in_bfd->flags & DYNAMIC) != 0)
17583d8817e4Smiod     {
17593d8817e4Smiod       bfd_size_type pad = 0;
17603d8817e4Smiod       int text_align_power;
17613d8817e4Smiod 
17623d8817e4Smiod       text_align_power = bfd_xcoff_text_align_power (in_bfd);
17633d8817e4Smiod 
17643d8817e4Smiod       pad = 1 << text_align_power;
17653d8817e4Smiod       pad -= (*offset + ar_header_size) & (pad - 1);
17663d8817e4Smiod 
17673d8817e4Smiod       if (! do_pad (out_bfd, pad))
17683d8817e4Smiod 	return FALSE;
17693d8817e4Smiod 
17703d8817e4Smiod       *offset += pad;
17713d8817e4Smiod     }
17723d8817e4Smiod 
17733d8817e4Smiod   return TRUE;
17743d8817e4Smiod }
17753d8817e4Smiod 
17763d8817e4Smiod static bfd_boolean
xcoff_write_armap_big(abfd,elength,map,orl_count,stridx)17773d8817e4Smiod xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
17783d8817e4Smiod      bfd *abfd;
17793d8817e4Smiod      unsigned int elength ATTRIBUTE_UNUSED;
17803d8817e4Smiod      struct orl *map;
17813d8817e4Smiod      unsigned int orl_count;
17823d8817e4Smiod      int stridx;
17833d8817e4Smiod {
17843d8817e4Smiod   struct xcoff_ar_file_hdr_big *fhdr;
17853d8817e4Smiod   bfd_vma i, sym_32, sym_64, str_32, str_64;
17863d8817e4Smiod   const bfd_arch_info_type *arch_info = NULL;
17873d8817e4Smiod   bfd *current_bfd;
17883d8817e4Smiod   size_t string_length;
17893d8817e4Smiod   file_ptr nextoff, prevoff;
17903d8817e4Smiod 
17913d8817e4Smiod   /* First, we look through the symbols and work out which are
17923d8817e4Smiod      from 32-bit objects and which from 64-bit ones.  */
17933d8817e4Smiod   sym_32 = sym_64 = str_32 = str_64 = 0;
17943d8817e4Smiod 
17953d8817e4Smiod   current_bfd = abfd->archive_head;
17963d8817e4Smiod   if (current_bfd != NULL)
17973d8817e4Smiod     arch_info = bfd_get_arch_info (current_bfd);
17983d8817e4Smiod     i = 0;
17993d8817e4Smiod     while (current_bfd != NULL && i < orl_count)
18003d8817e4Smiod     {
18013d8817e4Smiod       while (map[i].u.abfd == current_bfd)
18023d8817e4Smiod 	{
18033d8817e4Smiod 	  string_length = strlen (*map[i].name) + 1;
18043d8817e4Smiod 
18053d8817e4Smiod 	  if (arch_info->bits_per_address == 64)
18063d8817e4Smiod 	    {
18073d8817e4Smiod 	      sym_64++;
18083d8817e4Smiod 	      str_64 += string_length;
18093d8817e4Smiod 	    }
18103d8817e4Smiod 	  else
18113d8817e4Smiod 	    {
18123d8817e4Smiod 	      sym_32++;
18133d8817e4Smiod 	      str_32 += string_length;
18143d8817e4Smiod 	    }
18153d8817e4Smiod 	  i++;
18163d8817e4Smiod 	}
18173d8817e4Smiod       current_bfd = current_bfd->next;
18183d8817e4Smiod       if (current_bfd != NULL)
18193d8817e4Smiod 	arch_info = bfd_get_arch_info (current_bfd);
18203d8817e4Smiod     }
18213d8817e4Smiod 
18223d8817e4Smiod   /* A quick sanity check... */
18233d8817e4Smiod   BFD_ASSERT (sym_64 + sym_32 == orl_count);
18243d8817e4Smiod   /* Explicit cast to int for compiler.  */
18253d8817e4Smiod   BFD_ASSERT ((int)(str_64 + str_32) == stridx);
18263d8817e4Smiod 
18273d8817e4Smiod   fhdr = xcoff_ardata_big (abfd);
18283d8817e4Smiod 
18293d8817e4Smiod   /* xcoff_write_archive_contents_big passes nextoff in symoff. */
18303d8817e4Smiod   READ20 (fhdr->memoff, prevoff);
18313d8817e4Smiod   READ20 (fhdr->symoff, nextoff);
18323d8817e4Smiod 
18333d8817e4Smiod   BFD_ASSERT (nextoff == bfd_tell (abfd));
18343d8817e4Smiod 
18353d8817e4Smiod   /* Write out the symbol table.
18363d8817e4Smiod      Layout :
18373d8817e4Smiod 
18383d8817e4Smiod      standard big archive header
18393d8817e4Smiod      0x0000		      ar_size	[0x14]
18403d8817e4Smiod      0x0014		      ar_nxtmem [0x14]
18413d8817e4Smiod      0x0028		      ar_prvmem [0x14]
18423d8817e4Smiod      0x003C		      ar_date	[0x0C]
18433d8817e4Smiod      0x0048		      ar_uid	[0x0C]
18443d8817e4Smiod      0x0054		      ar_gid	[0x0C]
18453d8817e4Smiod      0x0060		      ar_mod	[0x0C]
18463d8817e4Smiod      0x006C		      ar_namelen[0x04]
18473d8817e4Smiod      0x0070		      ar_fmag	[SXCOFFARFMAG]
18483d8817e4Smiod 
18493d8817e4Smiod      Symbol table
18503d8817e4Smiod      0x0072		      num_syms	[0x08], binary
18513d8817e4Smiod      0x0078		      offsets	[0x08 * num_syms], binary
18523d8817e4Smiod      0x0086 + 0x08 * num_syms names	[??]
18533d8817e4Smiod      ??			      pad to even bytes.
18543d8817e4Smiod   */
18553d8817e4Smiod 
18563d8817e4Smiod   if (sym_32)
18573d8817e4Smiod     {
18583d8817e4Smiod       struct xcoff_ar_hdr_big *hdr;
18593d8817e4Smiod       char *symbol_table;
18603d8817e4Smiod       char *st;
18613d8817e4Smiod       file_ptr fileoff;
18623d8817e4Smiod 
18633d8817e4Smiod       bfd_vma symbol_table_size =
18643d8817e4Smiod 	SIZEOF_AR_HDR_BIG
18653d8817e4Smiod 	+ SXCOFFARFMAG
18663d8817e4Smiod 	+ 8
18673d8817e4Smiod 	+ 8 * sym_32
18683d8817e4Smiod 	+ str_32 + (str_32 & 1);
18693d8817e4Smiod 
18703d8817e4Smiod       symbol_table = bfd_zmalloc (symbol_table_size);
18713d8817e4Smiod       if (symbol_table == NULL)
18723d8817e4Smiod 	return FALSE;
18733d8817e4Smiod 
18743d8817e4Smiod       hdr = (struct xcoff_ar_hdr_big *) symbol_table;
18753d8817e4Smiod 
18763d8817e4Smiod       PRINT20 (hdr->size, 8 + 8 * sym_32 + str_32 + (str_32 & 1));
18773d8817e4Smiod 
18783d8817e4Smiod       if (sym_64)
18793d8817e4Smiod 	PRINT20 (hdr->nextoff, nextoff + symbol_table_size);
18803d8817e4Smiod       else
18813d8817e4Smiod 	PRINT20 (hdr->nextoff, 0);
18823d8817e4Smiod 
18833d8817e4Smiod       PRINT20 (hdr->prevoff, prevoff);
18843d8817e4Smiod       PRINT12 (hdr->date, 0);
18853d8817e4Smiod       PRINT12 (hdr->uid, 0);
18863d8817e4Smiod       PRINT12 (hdr->gid, 0);
18873d8817e4Smiod       PRINT12 (hdr->mode, 0);
18883d8817e4Smiod       PRINT4 (hdr->namlen, 0) ;
18893d8817e4Smiod 
18903d8817e4Smiod       st = symbol_table + SIZEOF_AR_HDR_BIG;
18913d8817e4Smiod       memcpy (st, XCOFFARFMAG, SXCOFFARFMAG);
18923d8817e4Smiod       st += SXCOFFARFMAG;
18933d8817e4Smiod 
18943d8817e4Smiod       bfd_h_put_64 (abfd, sym_32, st);
18953d8817e4Smiod       st += 8;
18963d8817e4Smiod 
18973d8817e4Smiod       /* loop over the 32 bit offsets */
18983d8817e4Smiod       current_bfd = abfd->archive_head;
18993d8817e4Smiod       if (current_bfd != NULL)
19003d8817e4Smiod 	arch_info = bfd_get_arch_info (current_bfd);
19013d8817e4Smiod       fileoff = SIZEOF_AR_FILE_HDR_BIG;
19023d8817e4Smiod       i = 0;
19033d8817e4Smiod       while (current_bfd != NULL && i < orl_count)
19043d8817e4Smiod 	{
19053d8817e4Smiod 	  while (map[i].u.abfd == current_bfd)
19063d8817e4Smiod 	    {
19073d8817e4Smiod 	      if (arch_info->bits_per_address == 32)
19083d8817e4Smiod 		{
19093d8817e4Smiod 		  bfd_h_put_64 (abfd, fileoff, st);
19103d8817e4Smiod 		  st += 8;
19113d8817e4Smiod 		}
19123d8817e4Smiod 	      i++;
19133d8817e4Smiod 	    }
19143d8817e4Smiod 	  string_length = strlen (normalize_filename (current_bfd));
19153d8817e4Smiod 	  string_length += string_length & 1;
19163d8817e4Smiod 	  fileoff += (SIZEOF_AR_HDR_BIG
19173d8817e4Smiod 		      + string_length
19183d8817e4Smiod 		      + SXCOFFARFMAG
19193d8817e4Smiod 		      + arelt_size (current_bfd));
19203d8817e4Smiod 	  fileoff += fileoff & 1;
19213d8817e4Smiod 	  current_bfd = current_bfd->next;
19223d8817e4Smiod 	  if (current_bfd != NULL)
19233d8817e4Smiod 	    arch_info = bfd_get_arch_info (current_bfd);
19243d8817e4Smiod 	}
19253d8817e4Smiod 
19263d8817e4Smiod       /* loop over the 32 bit symbol names */
19273d8817e4Smiod       current_bfd = abfd->archive_head;
19283d8817e4Smiod       if (current_bfd != NULL)
19293d8817e4Smiod 	arch_info = bfd_get_arch_info (current_bfd);
19303d8817e4Smiod       i = 0;
19313d8817e4Smiod       while (current_bfd != NULL && i < orl_count)
19323d8817e4Smiod 	{
19333d8817e4Smiod 	  while (map[i].u.abfd == current_bfd)
19343d8817e4Smiod 	    {
19353d8817e4Smiod 	      if (arch_info->bits_per_address == 32)
19363d8817e4Smiod 		{
19373d8817e4Smiod 		  string_length = sprintf (st, "%s", *map[i].name);
19383d8817e4Smiod 		  st += string_length + 1;
19393d8817e4Smiod 		}
19403d8817e4Smiod 	      i++;
19413d8817e4Smiod 	    }
19423d8817e4Smiod 	  current_bfd = current_bfd->next;
19433d8817e4Smiod 	  if (current_bfd != NULL)
19443d8817e4Smiod 	    arch_info = bfd_get_arch_info (current_bfd);
19453d8817e4Smiod 	}
19463d8817e4Smiod 
19473d8817e4Smiod       bfd_bwrite (symbol_table, symbol_table_size, abfd);
19483d8817e4Smiod 
19493d8817e4Smiod       free (symbol_table);
19503d8817e4Smiod 
19513d8817e4Smiod       prevoff = nextoff;
19523d8817e4Smiod       nextoff = nextoff + symbol_table_size;
19533d8817e4Smiod     }
19543d8817e4Smiod   else
19553d8817e4Smiod     PRINT20 (fhdr->symoff, 0);
19563d8817e4Smiod 
19573d8817e4Smiod   if (sym_64)
19583d8817e4Smiod     {
19593d8817e4Smiod       struct xcoff_ar_hdr_big *hdr;
19603d8817e4Smiod       char *symbol_table;
19613d8817e4Smiod       char *st;
19623d8817e4Smiod       file_ptr fileoff;
19633d8817e4Smiod 
19643d8817e4Smiod       bfd_vma symbol_table_size =
19653d8817e4Smiod 	SIZEOF_AR_HDR_BIG
19663d8817e4Smiod 	+ SXCOFFARFMAG
19673d8817e4Smiod 	+ 8
19683d8817e4Smiod 	+ 8 * sym_64
19693d8817e4Smiod 	+ str_64 + (str_64 & 1);
19703d8817e4Smiod 
19713d8817e4Smiod       symbol_table = bfd_zmalloc (symbol_table_size);
19723d8817e4Smiod       if (symbol_table == NULL)
19733d8817e4Smiod 	return FALSE;
19743d8817e4Smiod 
19753d8817e4Smiod       hdr = (struct xcoff_ar_hdr_big *) symbol_table;
19763d8817e4Smiod 
19773d8817e4Smiod       PRINT20 (hdr->size, 8 + 8 * sym_64 + str_64 + (str_64 & 1));
19783d8817e4Smiod       PRINT20 (hdr->nextoff, 0);
19793d8817e4Smiod       PRINT20 (hdr->prevoff, prevoff);
19803d8817e4Smiod       PRINT12 (hdr->date, 0);
19813d8817e4Smiod       PRINT12 (hdr->uid, 0);
19823d8817e4Smiod       PRINT12 (hdr->gid, 0);
19833d8817e4Smiod       PRINT12 (hdr->mode, 0);
19843d8817e4Smiod       PRINT4 (hdr->namlen, 0);
19853d8817e4Smiod 
19863d8817e4Smiod       st = symbol_table + SIZEOF_AR_HDR_BIG;
19873d8817e4Smiod       memcpy (st, XCOFFARFMAG, SXCOFFARFMAG);
19883d8817e4Smiod       st += SXCOFFARFMAG;
19893d8817e4Smiod 
19903d8817e4Smiod       bfd_h_put_64 (abfd, sym_64, st);
19913d8817e4Smiod       st += 8;
19923d8817e4Smiod 
19933d8817e4Smiod       /* loop over the 64 bit offsets */
19943d8817e4Smiod       current_bfd = abfd->archive_head;
19953d8817e4Smiod       if (current_bfd != NULL)
19963d8817e4Smiod 	arch_info = bfd_get_arch_info (current_bfd);
19973d8817e4Smiod       fileoff = SIZEOF_AR_FILE_HDR_BIG;
19983d8817e4Smiod       i = 0;
19993d8817e4Smiod       while (current_bfd != NULL && i < orl_count)
20003d8817e4Smiod 	{
20013d8817e4Smiod 	  while (map[i].u.abfd == current_bfd)
20023d8817e4Smiod 	    {
20033d8817e4Smiod 	      if (arch_info->bits_per_address == 64)
20043d8817e4Smiod 		{
20053d8817e4Smiod 		  bfd_h_put_64 (abfd, fileoff, st);
20063d8817e4Smiod 		  st += 8;
20073d8817e4Smiod 		}
20083d8817e4Smiod 	      i++;
20093d8817e4Smiod 	    }
20103d8817e4Smiod 	  string_length = strlen (normalize_filename (current_bfd));
20113d8817e4Smiod 	  string_length += string_length & 1;
20123d8817e4Smiod 	  fileoff += (SIZEOF_AR_HDR_BIG
20133d8817e4Smiod 		      + string_length
20143d8817e4Smiod 		      + SXCOFFARFMAG
20153d8817e4Smiod 		      + arelt_size (current_bfd));
20163d8817e4Smiod 	  fileoff += fileoff & 1;
20173d8817e4Smiod 	  current_bfd = current_bfd->next;
20183d8817e4Smiod 	  if (current_bfd != NULL)
20193d8817e4Smiod 	    arch_info = bfd_get_arch_info (current_bfd);
20203d8817e4Smiod 	}
20213d8817e4Smiod 
20223d8817e4Smiod       /* loop over the 64 bit symbol names */
20233d8817e4Smiod       current_bfd = abfd->archive_head;
20243d8817e4Smiod       if (current_bfd != NULL)
20253d8817e4Smiod 	arch_info = bfd_get_arch_info (current_bfd);
20263d8817e4Smiod       i = 0;
20273d8817e4Smiod       while (current_bfd != NULL && i < orl_count)
20283d8817e4Smiod 	{
20293d8817e4Smiod 	  while (map[i].u.abfd == current_bfd)
20303d8817e4Smiod 	    {
20313d8817e4Smiod 	      if (arch_info->bits_per_address == 64)
20323d8817e4Smiod 		{
20333d8817e4Smiod 		  string_length = sprintf (st, "%s", *map[i].name);
20343d8817e4Smiod 		  st += string_length + 1;
20353d8817e4Smiod 		}
20363d8817e4Smiod 	      i++;
20373d8817e4Smiod 	    }
20383d8817e4Smiod 	  current_bfd = current_bfd->next;
20393d8817e4Smiod 	  if (current_bfd != NULL)
20403d8817e4Smiod 	    arch_info = bfd_get_arch_info (current_bfd);
20413d8817e4Smiod 	}
20423d8817e4Smiod 
20433d8817e4Smiod       bfd_bwrite (symbol_table, symbol_table_size, abfd);
20443d8817e4Smiod 
20453d8817e4Smiod       free (symbol_table);
20463d8817e4Smiod 
20473d8817e4Smiod       PRINT20 (fhdr->symoff64, nextoff);
20483d8817e4Smiod     }
20493d8817e4Smiod   else
20503d8817e4Smiod     PRINT20 (fhdr->symoff64, 0);
20513d8817e4Smiod 
20523d8817e4Smiod   return TRUE;
20533d8817e4Smiod }
20543d8817e4Smiod 
20553d8817e4Smiod bfd_boolean
_bfd_xcoff_write_armap(abfd,elength,map,orl_count,stridx)20563d8817e4Smiod _bfd_xcoff_write_armap (abfd, elength, map, orl_count, stridx)
20573d8817e4Smiod      bfd *abfd;
20583d8817e4Smiod      unsigned int elength ATTRIBUTE_UNUSED;
20593d8817e4Smiod      struct orl *map;
20603d8817e4Smiod      unsigned int orl_count;
20613d8817e4Smiod      int stridx;
20623d8817e4Smiod {
20633d8817e4Smiod   if (! xcoff_big_format_p (abfd))
20643d8817e4Smiod     return xcoff_write_armap_old (abfd, elength, map, orl_count, stridx);
20653d8817e4Smiod   else
20663d8817e4Smiod     return xcoff_write_armap_big (abfd, elength, map, orl_count, stridx);
20673d8817e4Smiod }
20683d8817e4Smiod 
20693d8817e4Smiod /* Write out an XCOFF archive.  We always write an entire archive,
20703d8817e4Smiod    rather than fussing with the freelist and so forth.  */
20713d8817e4Smiod 
20723d8817e4Smiod static bfd_boolean
xcoff_write_archive_contents_old(abfd)20733d8817e4Smiod xcoff_write_archive_contents_old (abfd)
20743d8817e4Smiod      bfd *abfd;
20753d8817e4Smiod {
20763d8817e4Smiod   struct xcoff_ar_file_hdr fhdr;
20773d8817e4Smiod   bfd_size_type count;
20783d8817e4Smiod   bfd_size_type total_namlen;
20793d8817e4Smiod   file_ptr *offsets;
20803d8817e4Smiod   bfd_boolean makemap;
20813d8817e4Smiod   bfd_boolean hasobjects;
20823d8817e4Smiod   file_ptr prevoff, nextoff;
20833d8817e4Smiod   bfd *sub;
20843d8817e4Smiod   size_t i;
20853d8817e4Smiod   struct xcoff_ar_hdr ahdr;
20863d8817e4Smiod   bfd_size_type size;
20873d8817e4Smiod   char *p;
20883d8817e4Smiod   char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1];
20893d8817e4Smiod 
20903d8817e4Smiod   memset (&fhdr, 0, sizeof fhdr);
20913d8817e4Smiod   (void) strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG);
20923d8817e4Smiod   sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR);
20933d8817e4Smiod   sprintf (fhdr.freeoff, "%d", 0);
20943d8817e4Smiod 
20953d8817e4Smiod   count = 0;
20963d8817e4Smiod   total_namlen = 0;
20973d8817e4Smiod   for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
20983d8817e4Smiod     {
20993d8817e4Smiod       ++count;
21003d8817e4Smiod       total_namlen += strlen (normalize_filename (sub)) + 1;
21013d8817e4Smiod     }
21023d8817e4Smiod   offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
21033d8817e4Smiod   if (offsets == NULL)
21043d8817e4Smiod     return FALSE;
21053d8817e4Smiod 
21063d8817e4Smiod   if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0)
21073d8817e4Smiod     return FALSE;
21083d8817e4Smiod 
21093d8817e4Smiod   makemap = bfd_has_map (abfd);
21103d8817e4Smiod   hasobjects = FALSE;
21113d8817e4Smiod   prevoff = 0;
21123d8817e4Smiod   nextoff = SIZEOF_AR_FILE_HDR;
21133d8817e4Smiod   for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++)
21143d8817e4Smiod     {
21153d8817e4Smiod       const char *name;
21163d8817e4Smiod       bfd_size_type namlen;
21173d8817e4Smiod       struct xcoff_ar_hdr *ahdrp;
21183d8817e4Smiod       bfd_size_type remaining;
21193d8817e4Smiod 
21203d8817e4Smiod       if (makemap && ! hasobjects)
21213d8817e4Smiod 	{
21223d8817e4Smiod 	  if (bfd_check_format (sub, bfd_object))
21233d8817e4Smiod 	    hasobjects = TRUE;
21243d8817e4Smiod 	}
21253d8817e4Smiod 
21263d8817e4Smiod       name = normalize_filename (sub);
21273d8817e4Smiod       namlen = strlen (name);
21283d8817e4Smiod 
21293d8817e4Smiod       if (sub->arelt_data != NULL)
21303d8817e4Smiod 	ahdrp = arch_xhdr (sub);
21313d8817e4Smiod       else
21323d8817e4Smiod 	ahdrp = NULL;
21333d8817e4Smiod 
21343d8817e4Smiod       if (ahdrp == NULL)
21353d8817e4Smiod 	{
21363d8817e4Smiod 	  struct stat s;
21373d8817e4Smiod 
21383d8817e4Smiod 	  memset (&ahdr, 0, sizeof ahdr);
21393d8817e4Smiod 	  ahdrp = &ahdr;
21403d8817e4Smiod 	  if (stat (bfd_get_filename (sub), &s) != 0)
21413d8817e4Smiod 	    {
21423d8817e4Smiod 	      bfd_set_error (bfd_error_system_call);
21433d8817e4Smiod 	      return FALSE;
21443d8817e4Smiod 	    }
21453d8817e4Smiod 
21463d8817e4Smiod 	  sprintf (ahdrp->size, "%ld", (long) s.st_size);
2147*d04417c8Smiod 	  sprintf (ahdrp->date, "%lld", (long long) s.st_mtime);
21483d8817e4Smiod 	  sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
21493d8817e4Smiod 	  sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
21503d8817e4Smiod 	  sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
21513d8817e4Smiod 
21523d8817e4Smiod 	  if (sub->arelt_data == NULL)
21533d8817e4Smiod 	    {
21543d8817e4Smiod 	      size = sizeof (struct areltdata);
21553d8817e4Smiod 	      sub->arelt_data = bfd_alloc (sub, size);
21563d8817e4Smiod 	      if (sub->arelt_data == NULL)
21573d8817e4Smiod 		return FALSE;
21583d8817e4Smiod 	    }
21593d8817e4Smiod 
21603d8817e4Smiod 	  arch_eltdata (sub)->parsed_size = s.st_size;
21613d8817e4Smiod 	}
21623d8817e4Smiod 
21633d8817e4Smiod       sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
21643d8817e4Smiod       sprintf (ahdrp->namlen, "%ld", (long) namlen);
21653d8817e4Smiod 
21663d8817e4Smiod       /* If the length of the name is odd, we write out the null byte
21673d8817e4Smiod 	 after the name as well.  */
21683d8817e4Smiod       namlen = (namlen + 1) &~ (bfd_size_type) 1;
21693d8817e4Smiod 
21703d8817e4Smiod       remaining = arelt_size (sub);
21713d8817e4Smiod       size = (SIZEOF_AR_HDR
21723d8817e4Smiod 	      + namlen
21733d8817e4Smiod 	      + SXCOFFARFMAG
21743d8817e4Smiod 	      + remaining);
21753d8817e4Smiod 
21763d8817e4Smiod       BFD_ASSERT (nextoff == bfd_tell (abfd));
21773d8817e4Smiod 
21783d8817e4Smiod       offsets[i] = nextoff;
21793d8817e4Smiod 
21803d8817e4Smiod       prevoff = nextoff;
21813d8817e4Smiod       nextoff += size + (size & 1);
21823d8817e4Smiod 
21833d8817e4Smiod       sprintf (ahdrp->nextoff, "%ld", (long) nextoff);
21843d8817e4Smiod 
21853d8817e4Smiod       /* We need spaces, not null bytes, in the header.  */
21863d8817e4Smiod       for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++)
21873d8817e4Smiod 	if (*p == '\0')
21883d8817e4Smiod 	  *p = ' ';
21893d8817e4Smiod 
21903d8817e4Smiod       if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR, abfd)
21913d8817e4Smiod 	   != SIZEOF_AR_HDR)
21923d8817e4Smiod 	  || bfd_bwrite ((PTR) name, namlen, abfd) != namlen
21933d8817e4Smiod 	  || bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG,
21943d8817e4Smiod 			 abfd) != SXCOFFARFMAG)
21953d8817e4Smiod 	return FALSE;
21963d8817e4Smiod 
21973d8817e4Smiod       if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
21983d8817e4Smiod 	return FALSE;
21993d8817e4Smiod 
22003d8817e4Smiod       if (! do_copy (abfd, sub))
22013d8817e4Smiod 	return FALSE;
22023d8817e4Smiod 
22033d8817e4Smiod       if (! do_pad (abfd, size & 1))
22043d8817e4Smiod 	return FALSE;
22053d8817e4Smiod     }
22063d8817e4Smiod 
22073d8817e4Smiod   sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
22083d8817e4Smiod 
22093d8817e4Smiod   /* Write out the member table.  */
22103d8817e4Smiod 
22113d8817e4Smiod   BFD_ASSERT (nextoff == bfd_tell (abfd));
22123d8817e4Smiod   sprintf (fhdr.memoff, "%ld", (long) nextoff);
22133d8817e4Smiod 
22143d8817e4Smiod   memset (&ahdr, 0, sizeof ahdr);
22153d8817e4Smiod   sprintf (ahdr.size, "%ld", (long) (XCOFFARMAG_ELEMENT_SIZE
22163d8817e4Smiod 				     + count * XCOFFARMAG_ELEMENT_SIZE
22173d8817e4Smiod 				     + total_namlen));
22183d8817e4Smiod   sprintf (ahdr.prevoff, "%ld", (long) prevoff);
22193d8817e4Smiod   sprintf (ahdr.date, "%d", 0);
22203d8817e4Smiod   sprintf (ahdr.uid, "%d", 0);
22213d8817e4Smiod   sprintf (ahdr.gid, "%d", 0);
22223d8817e4Smiod   sprintf (ahdr.mode, "%d", 0);
22233d8817e4Smiod   sprintf (ahdr.namlen, "%d", 0);
22243d8817e4Smiod 
22253d8817e4Smiod   size = (SIZEOF_AR_HDR
22263d8817e4Smiod 	  + XCOFFARMAG_ELEMENT_SIZE
22273d8817e4Smiod 	  + count * XCOFFARMAG_ELEMENT_SIZE
22283d8817e4Smiod 	  + total_namlen
22293d8817e4Smiod 	  + SXCOFFARFMAG);
22303d8817e4Smiod 
22313d8817e4Smiod   prevoff = nextoff;
22323d8817e4Smiod   nextoff += size + (size & 1);
22333d8817e4Smiod 
22343d8817e4Smiod   if (makemap && hasobjects)
22353d8817e4Smiod     sprintf (ahdr.nextoff, "%ld", (long) nextoff);
22363d8817e4Smiod   else
22373d8817e4Smiod     sprintf (ahdr.nextoff, "%d", 0);
22383d8817e4Smiod 
22393d8817e4Smiod   /* We need spaces, not null bytes, in the header.  */
22403d8817e4Smiod   for (p = (char *) &ahdr; p < (char *) &ahdr + SIZEOF_AR_HDR; p++)
22413d8817e4Smiod     if (*p == '\0')
22423d8817e4Smiod       *p = ' ';
22433d8817e4Smiod 
22443d8817e4Smiod   if ((bfd_bwrite ((PTR) &ahdr, (bfd_size_type) SIZEOF_AR_HDR, abfd)
22453d8817e4Smiod        != SIZEOF_AR_HDR)
22463d8817e4Smiod       || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd)
22473d8817e4Smiod 	  != SXCOFFARFMAG))
22483d8817e4Smiod     return FALSE;
22493d8817e4Smiod 
22503d8817e4Smiod   sprintf (decbuf, "%-12ld", (long) count);
22513d8817e4Smiod   if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE, abfd)
22523d8817e4Smiod       != XCOFFARMAG_ELEMENT_SIZE)
22533d8817e4Smiod     return FALSE;
22543d8817e4Smiod   for (i = 0; i < (size_t) count; i++)
22553d8817e4Smiod     {
22563d8817e4Smiod       sprintf (decbuf, "%-12ld", (long) offsets[i]);
22573d8817e4Smiod       if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE,
22583d8817e4Smiod 		      abfd) != XCOFFARMAG_ELEMENT_SIZE)
22593d8817e4Smiod 	return FALSE;
22603d8817e4Smiod     }
22613d8817e4Smiod   for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
22623d8817e4Smiod     {
22633d8817e4Smiod       const char *name;
22643d8817e4Smiod       bfd_size_type namlen;
22653d8817e4Smiod 
22663d8817e4Smiod       name = normalize_filename (sub);
22673d8817e4Smiod       namlen = strlen (name);
22683d8817e4Smiod       if (bfd_bwrite ((PTR) name, namlen + 1, abfd) != namlen + 1)
22693d8817e4Smiod 	return FALSE;
22703d8817e4Smiod     }
22713d8817e4Smiod 
22723d8817e4Smiod   if (! do_pad (abfd, size & 1))
22733d8817e4Smiod     return FALSE;
22743d8817e4Smiod 
22753d8817e4Smiod   /* Write out the armap, if appropriate.  */
22763d8817e4Smiod   if (! makemap || ! hasobjects)
22773d8817e4Smiod     sprintf (fhdr.symoff, "%d", 0);
22783d8817e4Smiod   else
22793d8817e4Smiod     {
22803d8817e4Smiod       BFD_ASSERT (nextoff == bfd_tell (abfd));
22813d8817e4Smiod       sprintf (fhdr.symoff, "%ld", (long) nextoff);
22823d8817e4Smiod       bfd_ardata (abfd)->tdata = (PTR) &fhdr;
22833d8817e4Smiod       if (! _bfd_compute_and_write_armap (abfd, 0))
22843d8817e4Smiod 	return FALSE;
22853d8817e4Smiod     }
22863d8817e4Smiod 
22873d8817e4Smiod   /* Write out the archive file header.  */
22883d8817e4Smiod 
22893d8817e4Smiod   /* We need spaces, not null bytes, in the header.  */
22903d8817e4Smiod   for (p = (char *) &fhdr; p < (char *) &fhdr + SIZEOF_AR_FILE_HDR; p++)
22913d8817e4Smiod     if (*p == '\0')
22923d8817e4Smiod       *p = ' ';
22933d8817e4Smiod 
22943d8817e4Smiod   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
22953d8817e4Smiod       || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR, abfd)
22963d8817e4Smiod 	  != SIZEOF_AR_FILE_HDR))
22973d8817e4Smiod     return FALSE;
22983d8817e4Smiod 
22993d8817e4Smiod   return TRUE;
23003d8817e4Smiod }
23013d8817e4Smiod 
23023d8817e4Smiod static bfd_boolean
xcoff_write_archive_contents_big(abfd)23033d8817e4Smiod xcoff_write_archive_contents_big (abfd)
23043d8817e4Smiod      bfd *abfd;
23053d8817e4Smiod {
23063d8817e4Smiod   struct xcoff_ar_file_hdr_big fhdr;
23073d8817e4Smiod   bfd_size_type count;
23083d8817e4Smiod   bfd_size_type total_namlen;
23093d8817e4Smiod   file_ptr *offsets;
23103d8817e4Smiod   bfd_boolean makemap;
23113d8817e4Smiod   bfd_boolean hasobjects;
23123d8817e4Smiod   file_ptr prevoff, nextoff;
23133d8817e4Smiod   bfd *current_bfd;
23143d8817e4Smiod   size_t i;
23153d8817e4Smiod   struct xcoff_ar_hdr_big *hdr, ahdr;
23163d8817e4Smiod   bfd_size_type size;
23173d8817e4Smiod   char *member_table, *mt;
23183d8817e4Smiod   bfd_vma member_table_size;
23193d8817e4Smiod 
23203d8817e4Smiod   memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG);
23213d8817e4Smiod   memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
23223d8817e4Smiod 
23233d8817e4Smiod   if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR_BIG, SEEK_SET) != 0)
23243d8817e4Smiod     return FALSE;
23253d8817e4Smiod 
23263d8817e4Smiod   /* Calculate count and total_namlen.  */
23273d8817e4Smiod   makemap = bfd_has_map (abfd);
23283d8817e4Smiod   hasobjects = FALSE;
23293d8817e4Smiod   for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0;
23303d8817e4Smiod        current_bfd != NULL;
23313d8817e4Smiod        current_bfd = current_bfd->next, count++)
23323d8817e4Smiod     {
23333d8817e4Smiod       total_namlen += strlen (normalize_filename (current_bfd)) + 1;
23343d8817e4Smiod 
23353d8817e4Smiod       if (makemap
23363d8817e4Smiod 	  && ! hasobjects
23373d8817e4Smiod 	  && bfd_check_format (current_bfd, bfd_object))
23383d8817e4Smiod 	hasobjects = TRUE;
23393d8817e4Smiod     }
23403d8817e4Smiod 
23413d8817e4Smiod   offsets = NULL;
23423d8817e4Smiod   if (count)
23433d8817e4Smiod     {
23443d8817e4Smiod       offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr));
23453d8817e4Smiod       if (offsets == NULL)
23463d8817e4Smiod 	return FALSE;
23473d8817e4Smiod     }
23483d8817e4Smiod 
23493d8817e4Smiod   prevoff = 0;
23503d8817e4Smiod   nextoff = SIZEOF_AR_FILE_HDR_BIG;
23513d8817e4Smiod   for (current_bfd = abfd->archive_head, i = 0;
23523d8817e4Smiod        current_bfd != NULL;
23533d8817e4Smiod        current_bfd = current_bfd->next, i++)
23543d8817e4Smiod     {
23553d8817e4Smiod       const char *name;
23563d8817e4Smiod       bfd_size_type namlen;
23573d8817e4Smiod       struct xcoff_ar_hdr_big *ahdrp;
23583d8817e4Smiod       bfd_size_type remaining;
23593d8817e4Smiod 
23603d8817e4Smiod       name = normalize_filename (current_bfd);
23613d8817e4Smiod       namlen = strlen (name);
23623d8817e4Smiod 
23633d8817e4Smiod       if (current_bfd->arelt_data != NULL)
23643d8817e4Smiod 	ahdrp = arch_xhdr_big (current_bfd);
23653d8817e4Smiod       else
23663d8817e4Smiod 	ahdrp = NULL;
23673d8817e4Smiod 
23683d8817e4Smiod       if (ahdrp == NULL)
23693d8817e4Smiod 	{
23703d8817e4Smiod 	  struct stat s;
23713d8817e4Smiod 
23723d8817e4Smiod 	  ahdrp = &ahdr;
23733d8817e4Smiod 	  /* XXX This should actually be a call to stat64 (at least on
23743d8817e4Smiod 	     32-bit machines).
23753d8817e4Smiod 	     XXX This call will fail if the original object is not found.  */
23763d8817e4Smiod 	  if (stat (bfd_get_filename (current_bfd), &s) != 0)
23773d8817e4Smiod 	    {
23783d8817e4Smiod 	      bfd_set_error (bfd_error_system_call);
23793d8817e4Smiod 	      return FALSE;
23803d8817e4Smiod 	    }
23813d8817e4Smiod 
23823d8817e4Smiod 	  PRINT20 (ahdrp->size, s.st_size);
2383*d04417c8Smiod 	  PRINT12_LL (ahdrp->date, s.st_mtime);
23843d8817e4Smiod 	  PRINT12 (ahdrp->uid,  s.st_uid);
23853d8817e4Smiod 	  PRINT12 (ahdrp->gid,  s.st_gid);
23863d8817e4Smiod 	  PRINT12_OCTAL (ahdrp->mode, s.st_mode);
23873d8817e4Smiod 
23883d8817e4Smiod 	  if (current_bfd->arelt_data == NULL)
23893d8817e4Smiod 	    {
23903d8817e4Smiod 	      size = sizeof (struct areltdata);
23913d8817e4Smiod 	      current_bfd->arelt_data = bfd_alloc (current_bfd, size);
23923d8817e4Smiod 	      if (current_bfd->arelt_data == NULL)
23933d8817e4Smiod 		return FALSE;
23943d8817e4Smiod 	    }
23953d8817e4Smiod 
23963d8817e4Smiod 	  arch_eltdata (current_bfd)->parsed_size = s.st_size;
23973d8817e4Smiod 	}
23983d8817e4Smiod 
23993d8817e4Smiod       PRINT20 (ahdrp->prevoff, prevoff);
24003d8817e4Smiod       PRINT4 (ahdrp->namlen, namlen);
24013d8817e4Smiod 
24023d8817e4Smiod       /* If the length of the name is odd, we write out the null byte
24033d8817e4Smiod 	 after the name as well.  */
24043d8817e4Smiod       namlen = (namlen + 1) &~ (bfd_size_type) 1;
24053d8817e4Smiod 
24063d8817e4Smiod       remaining = arelt_size (current_bfd);
24073d8817e4Smiod       size = (SIZEOF_AR_HDR_BIG
24083d8817e4Smiod 	      + namlen
24093d8817e4Smiod 	      + SXCOFFARFMAG
24103d8817e4Smiod 	      + remaining);
24113d8817e4Smiod 
24123d8817e4Smiod       BFD_ASSERT (nextoff == bfd_tell (abfd));
24133d8817e4Smiod 
24143d8817e4Smiod       /* Check for xcoff shared objects.
24153d8817e4Smiod 	 Their text section needs to be aligned wrt the archive file position.
24163d8817e4Smiod 	 This requires extra padding before the archive header.  */
24173d8817e4Smiod       if (! do_shared_object_padding (abfd, current_bfd, & nextoff,
24183d8817e4Smiod 				      SIZEOF_AR_HDR_BIG + namlen
24193d8817e4Smiod 				      + SXCOFFARFMAG))
24203d8817e4Smiod 	return FALSE;
24213d8817e4Smiod 
24223d8817e4Smiod       offsets[i] = nextoff;
24233d8817e4Smiod 
24243d8817e4Smiod       prevoff = nextoff;
24253d8817e4Smiod       nextoff += size + (size & 1);
24263d8817e4Smiod 
24273d8817e4Smiod       PRINT20 (ahdrp->nextoff, nextoff);
24283d8817e4Smiod 
24293d8817e4Smiod       if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
24303d8817e4Smiod 	   != SIZEOF_AR_HDR_BIG)
24313d8817e4Smiod 	  || bfd_bwrite ((PTR) name, (bfd_size_type) namlen, abfd) != namlen
24323d8817e4Smiod 	  || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG,
24333d8817e4Smiod 			  abfd) != SXCOFFARFMAG))
24343d8817e4Smiod 	return FALSE;
24353d8817e4Smiod 
24363d8817e4Smiod       if (bfd_seek (current_bfd, (file_ptr) 0, SEEK_SET) != 0)
24373d8817e4Smiod 	return FALSE;
24383d8817e4Smiod 
24393d8817e4Smiod       if (! do_copy (abfd, current_bfd))
24403d8817e4Smiod 	return FALSE;
24413d8817e4Smiod 
24423d8817e4Smiod       if (! do_pad (abfd, size & 1))
24433d8817e4Smiod 	return FALSE;
24443d8817e4Smiod     }
24453d8817e4Smiod 
24463d8817e4Smiod   if (count)
24473d8817e4Smiod     {
24483d8817e4Smiod       PRINT20 (fhdr.firstmemoff, offsets[0]);
24493d8817e4Smiod       PRINT20 (fhdr.lastmemoff, prevoff);
24503d8817e4Smiod     }
24513d8817e4Smiod 
24523d8817e4Smiod   /* Write out the member table.
24533d8817e4Smiod      Layout :
24543d8817e4Smiod 
24553d8817e4Smiod      standard big archive header
24563d8817e4Smiod      0x0000		      ar_size	[0x14]
24573d8817e4Smiod      0x0014		      ar_nxtmem [0x14]
24583d8817e4Smiod      0x0028		      ar_prvmem [0x14]
24593d8817e4Smiod      0x003C		      ar_date	[0x0C]
24603d8817e4Smiod      0x0048		      ar_uid	[0x0C]
24613d8817e4Smiod      0x0054		      ar_gid	[0x0C]
24623d8817e4Smiod      0x0060		      ar_mod	[0x0C]
24633d8817e4Smiod      0x006C		      ar_namelen[0x04]
24643d8817e4Smiod      0x0070		      ar_fmag	[0x02]
24653d8817e4Smiod 
24663d8817e4Smiod      Member table
24673d8817e4Smiod      0x0072		      count	[0x14]
24683d8817e4Smiod      0x0086		      offsets	[0x14 * counts]
24693d8817e4Smiod      0x0086 + 0x14 * counts   names	[??]
24703d8817e4Smiod      ??			      pad to even bytes.
24713d8817e4Smiod    */
24723d8817e4Smiod 
24733d8817e4Smiod   BFD_ASSERT (nextoff == bfd_tell (abfd));
24743d8817e4Smiod 
24753d8817e4Smiod   member_table_size = (SIZEOF_AR_HDR_BIG
24763d8817e4Smiod 		       + SXCOFFARFMAG
24773d8817e4Smiod 		       + XCOFFARMAGBIG_ELEMENT_SIZE
24783d8817e4Smiod 		       + count * XCOFFARMAGBIG_ELEMENT_SIZE
24793d8817e4Smiod 		       + total_namlen);
24803d8817e4Smiod 
24813d8817e4Smiod   member_table_size += member_table_size & 1;
24823d8817e4Smiod   member_table = bfd_zmalloc (member_table_size);
24833d8817e4Smiod   if (member_table == NULL)
24843d8817e4Smiod     return FALSE;
24853d8817e4Smiod 
24863d8817e4Smiod   hdr = (struct xcoff_ar_hdr_big *) member_table;
24873d8817e4Smiod 
24883d8817e4Smiod   PRINT20 (hdr->size, (XCOFFARMAGBIG_ELEMENT_SIZE
24893d8817e4Smiod 		       + count * XCOFFARMAGBIG_ELEMENT_SIZE
24903d8817e4Smiod 		       + total_namlen + (total_namlen & 1)));
24913d8817e4Smiod   if (makemap && hasobjects)
24923d8817e4Smiod     PRINT20 (hdr->nextoff, nextoff + member_table_size);
24933d8817e4Smiod   else
24943d8817e4Smiod     PRINT20 (hdr->nextoff, 0);
24953d8817e4Smiod   PRINT20 (hdr->prevoff, prevoff);
24963d8817e4Smiod   PRINT12 (hdr->date, 0);
24973d8817e4Smiod   PRINT12 (hdr->uid, 0);
24983d8817e4Smiod   PRINT12 (hdr->gid, 0);
24993d8817e4Smiod   PRINT12 (hdr->mode, 0);
25003d8817e4Smiod   PRINT4 (hdr->namlen, 0);
25013d8817e4Smiod 
25023d8817e4Smiod   mt = member_table + SIZEOF_AR_HDR_BIG;
25033d8817e4Smiod   memcpy (mt, XCOFFARFMAG, SXCOFFARFMAG);
25043d8817e4Smiod   mt += SXCOFFARFMAG;
25053d8817e4Smiod 
25063d8817e4Smiod   PRINT20 (mt, count);
25073d8817e4Smiod   mt += XCOFFARMAGBIG_ELEMENT_SIZE;
25083d8817e4Smiod   for (i = 0; i < (size_t) count; i++)
25093d8817e4Smiod     {
25103d8817e4Smiod       PRINT20 (mt, offsets[i]);
25113d8817e4Smiod       mt += XCOFFARMAGBIG_ELEMENT_SIZE;
25123d8817e4Smiod     }
25133d8817e4Smiod 
25143d8817e4Smiod   if (count)
25153d8817e4Smiod     {
25163d8817e4Smiod       free (offsets);
25173d8817e4Smiod       offsets = NULL;
25183d8817e4Smiod     }
25193d8817e4Smiod 
25203d8817e4Smiod   for (current_bfd = abfd->archive_head; current_bfd != NULL;
25213d8817e4Smiod        current_bfd = current_bfd->next)
25223d8817e4Smiod     {
25233d8817e4Smiod       const char *name;
25243d8817e4Smiod       size_t namlen;
25253d8817e4Smiod 
25263d8817e4Smiod       name = normalize_filename (current_bfd);
25273d8817e4Smiod       namlen = sprintf (mt, "%s", name);
25283d8817e4Smiod       mt += namlen + 1;
25293d8817e4Smiod     }
25303d8817e4Smiod 
25313d8817e4Smiod   if (bfd_bwrite (member_table, member_table_size, abfd) != member_table_size)
25323d8817e4Smiod     return FALSE;
25333d8817e4Smiod 
25343d8817e4Smiod   free (member_table);
25353d8817e4Smiod 
25363d8817e4Smiod   PRINT20 (fhdr.memoff, nextoff);
25373d8817e4Smiod 
25383d8817e4Smiod   prevoff = nextoff;
25393d8817e4Smiod   nextoff += member_table_size;
25403d8817e4Smiod 
25413d8817e4Smiod   /* Write out the armap, if appropriate.  */
25423d8817e4Smiod 
25433d8817e4Smiod   if (! makemap || ! hasobjects)
25443d8817e4Smiod     PRINT20 (fhdr.symoff, 0);
25453d8817e4Smiod   else
25463d8817e4Smiod     {
25473d8817e4Smiod       BFD_ASSERT (nextoff == bfd_tell (abfd));
25483d8817e4Smiod 
25493d8817e4Smiod       /* Save nextoff in fhdr.symoff so the armap routine can use it.  */
25503d8817e4Smiod       PRINT20 (fhdr.symoff, nextoff);
25513d8817e4Smiod 
25523d8817e4Smiod       bfd_ardata (abfd)->tdata = (PTR) &fhdr;
25533d8817e4Smiod       if (! _bfd_compute_and_write_armap (abfd, 0))
25543d8817e4Smiod 	return FALSE;
25553d8817e4Smiod     }
25563d8817e4Smiod 
25573d8817e4Smiod   /* Write out the archive file header.  */
25583d8817e4Smiod 
25593d8817e4Smiod   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
25603d8817e4Smiod       || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR_BIG,
25613d8817e4Smiod 		      abfd) != SIZEOF_AR_FILE_HDR_BIG))
25623d8817e4Smiod     return FALSE;
25633d8817e4Smiod 
25643d8817e4Smiod   return TRUE;
25653d8817e4Smiod }
25663d8817e4Smiod 
25673d8817e4Smiod bfd_boolean
_bfd_xcoff_write_archive_contents(abfd)25683d8817e4Smiod _bfd_xcoff_write_archive_contents (abfd)
25693d8817e4Smiod      bfd *abfd;
25703d8817e4Smiod {
25713d8817e4Smiod   if (! xcoff_big_format_p (abfd))
25723d8817e4Smiod     return xcoff_write_archive_contents_old (abfd);
25733d8817e4Smiod   else
25743d8817e4Smiod     return xcoff_write_archive_contents_big (abfd);
25753d8817e4Smiod }
25763d8817e4Smiod 
25773d8817e4Smiod /* We can't use the usual coff_sizeof_headers routine, because AIX
25783d8817e4Smiod    always uses an a.out header.  */
25793d8817e4Smiod 
25803d8817e4Smiod int
_bfd_xcoff_sizeof_headers(abfd,reloc)25813d8817e4Smiod _bfd_xcoff_sizeof_headers (abfd, reloc)
25823d8817e4Smiod      bfd *abfd;
25833d8817e4Smiod      bfd_boolean reloc ATTRIBUTE_UNUSED;
25843d8817e4Smiod {
25853d8817e4Smiod   int size;
25863d8817e4Smiod 
25873d8817e4Smiod   size = FILHSZ;
25883d8817e4Smiod   if (xcoff_data (abfd)->full_aouthdr)
25893d8817e4Smiod     size += AOUTSZ;
25903d8817e4Smiod   else
25913d8817e4Smiod     size += SMALL_AOUTSZ;
25923d8817e4Smiod   size += abfd->section_count * SCNHSZ;
25933d8817e4Smiod   return size;
25943d8817e4Smiod }
25953d8817e4Smiod 
25963d8817e4Smiod /* Routines to swap information in the XCOFF .loader section.  If we
25973d8817e4Smiod    ever need to write an XCOFF loader, this stuff will need to be
25983d8817e4Smiod    moved to another file shared by the linker (which XCOFF calls the
25993d8817e4Smiod    ``binder'') and the loader.  */
26003d8817e4Smiod 
26013d8817e4Smiod /* Swap in the ldhdr structure.  */
26023d8817e4Smiod 
26033d8817e4Smiod static void
xcoff_swap_ldhdr_in(abfd,s,dst)26043d8817e4Smiod xcoff_swap_ldhdr_in (abfd, s, dst)
26053d8817e4Smiod      bfd *abfd;
26063d8817e4Smiod      const PTR s;
26073d8817e4Smiod      struct internal_ldhdr *dst;
26083d8817e4Smiod {
26093d8817e4Smiod   const struct external_ldhdr *src = (const struct external_ldhdr *) s;
26103d8817e4Smiod 
26113d8817e4Smiod   dst->l_version = bfd_get_32 (abfd, src->l_version);
26123d8817e4Smiod   dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
26133d8817e4Smiod   dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
26143d8817e4Smiod   dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
26153d8817e4Smiod   dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
26163d8817e4Smiod   dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
26173d8817e4Smiod   dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
26183d8817e4Smiod   dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
26193d8817e4Smiod }
26203d8817e4Smiod 
26213d8817e4Smiod /* Swap out the ldhdr structure.  */
26223d8817e4Smiod 
26233d8817e4Smiod static void
xcoff_swap_ldhdr_out(abfd,src,d)26243d8817e4Smiod xcoff_swap_ldhdr_out (abfd, src, d)
26253d8817e4Smiod      bfd *abfd;
26263d8817e4Smiod      const struct internal_ldhdr *src;
26273d8817e4Smiod      PTR d;
26283d8817e4Smiod {
26293d8817e4Smiod   struct external_ldhdr *dst = (struct external_ldhdr *) d;
26303d8817e4Smiod 
26313d8817e4Smiod   bfd_put_32 (abfd, (bfd_vma) src->l_version, dst->l_version);
26323d8817e4Smiod   bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
26333d8817e4Smiod   bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
26343d8817e4Smiod   bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
26353d8817e4Smiod   bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
26363d8817e4Smiod   bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
26373d8817e4Smiod   bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
26383d8817e4Smiod   bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
26393d8817e4Smiod }
26403d8817e4Smiod 
26413d8817e4Smiod /* Swap in the ldsym structure.  */
26423d8817e4Smiod 
26433d8817e4Smiod static void
xcoff_swap_ldsym_in(abfd,s,dst)26443d8817e4Smiod xcoff_swap_ldsym_in (abfd, s, dst)
26453d8817e4Smiod      bfd *abfd;
26463d8817e4Smiod      const PTR s;
26473d8817e4Smiod      struct internal_ldsym *dst;
26483d8817e4Smiod {
26493d8817e4Smiod   const struct external_ldsym *src = (const struct external_ldsym *) s;
26503d8817e4Smiod 
26513d8817e4Smiod   if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0) {
26523d8817e4Smiod     memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
26533d8817e4Smiod   } else {
26543d8817e4Smiod     dst->_l._l_l._l_zeroes = 0;
26553d8817e4Smiod     dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
26563d8817e4Smiod   }
26573d8817e4Smiod   dst->l_value = bfd_get_32 (abfd, src->l_value);
26583d8817e4Smiod   dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
26593d8817e4Smiod   dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
26603d8817e4Smiod   dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
26613d8817e4Smiod   dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
26623d8817e4Smiod   dst->l_parm = bfd_get_32 (abfd, src->l_parm);
26633d8817e4Smiod }
26643d8817e4Smiod 
26653d8817e4Smiod /* Swap out the ldsym structure.  */
26663d8817e4Smiod 
26673d8817e4Smiod static void
xcoff_swap_ldsym_out(abfd,src,d)26683d8817e4Smiod xcoff_swap_ldsym_out (abfd, src, d)
26693d8817e4Smiod      bfd *abfd;
26703d8817e4Smiod      const struct internal_ldsym *src;
26713d8817e4Smiod      PTR d;
26723d8817e4Smiod {
26733d8817e4Smiod   struct external_ldsym *dst = (struct external_ldsym *) d;
26743d8817e4Smiod 
26753d8817e4Smiod   if (src->_l._l_l._l_zeroes != 0)
26763d8817e4Smiod     memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
26773d8817e4Smiod   else
26783d8817e4Smiod     {
26793d8817e4Smiod       bfd_put_32 (abfd, (bfd_vma) 0, dst->_l._l_l._l_zeroes);
26803d8817e4Smiod       bfd_put_32 (abfd, (bfd_vma) src->_l._l_l._l_offset,
26813d8817e4Smiod 		  dst->_l._l_l._l_offset);
26823d8817e4Smiod     }
26833d8817e4Smiod   bfd_put_32 (abfd, src->l_value, dst->l_value);
26843d8817e4Smiod   bfd_put_16 (abfd, (bfd_vma) src->l_scnum, dst->l_scnum);
26853d8817e4Smiod   bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
26863d8817e4Smiod   bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
26873d8817e4Smiod   bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
26883d8817e4Smiod   bfd_put_32 (abfd, src->l_parm, dst->l_parm);
26893d8817e4Smiod }
26903d8817e4Smiod 
26913d8817e4Smiod static void
xcoff_swap_reloc_in(abfd,s,d)26923d8817e4Smiod xcoff_swap_reloc_in (abfd, s, d)
26933d8817e4Smiod      bfd *abfd;
26943d8817e4Smiod      PTR s;
26953d8817e4Smiod      PTR d;
26963d8817e4Smiod {
26973d8817e4Smiod   struct external_reloc *src = (struct external_reloc *) s;
26983d8817e4Smiod   struct internal_reloc *dst = (struct internal_reloc *) d;
26993d8817e4Smiod 
27003d8817e4Smiod   memset (dst, 0, sizeof (struct internal_reloc));
27013d8817e4Smiod 
27023d8817e4Smiod   dst->r_vaddr = bfd_get_32 (abfd, src->r_vaddr);
27033d8817e4Smiod   dst->r_symndx = bfd_get_32 (abfd, src->r_symndx);
27043d8817e4Smiod   dst->r_size = bfd_get_8 (abfd, src->r_size);
27053d8817e4Smiod   dst->r_type = bfd_get_8 (abfd, src->r_type);
27063d8817e4Smiod }
27073d8817e4Smiod 
27083d8817e4Smiod static unsigned int
xcoff_swap_reloc_out(abfd,s,d)27093d8817e4Smiod xcoff_swap_reloc_out (abfd, s, d)
27103d8817e4Smiod      bfd *abfd;
27113d8817e4Smiod      PTR s;
27123d8817e4Smiod      PTR d;
27133d8817e4Smiod {
27143d8817e4Smiod   struct internal_reloc *src = (struct internal_reloc *) s;
27153d8817e4Smiod   struct external_reloc *dst = (struct external_reloc *) d;
27163d8817e4Smiod 
27173d8817e4Smiod   bfd_put_32 (abfd, src->r_vaddr, dst->r_vaddr);
27183d8817e4Smiod   bfd_put_32 (abfd, src->r_symndx, dst->r_symndx);
27193d8817e4Smiod   bfd_put_8 (abfd, src->r_type, dst->r_type);
27203d8817e4Smiod   bfd_put_8 (abfd, src->r_size, dst->r_size);
27213d8817e4Smiod 
27223d8817e4Smiod   return bfd_coff_relsz (abfd);
27233d8817e4Smiod }
27243d8817e4Smiod 
27253d8817e4Smiod /* Swap in the ldrel structure.  */
27263d8817e4Smiod 
27273d8817e4Smiod static void
xcoff_swap_ldrel_in(abfd,s,dst)27283d8817e4Smiod xcoff_swap_ldrel_in (abfd, s, dst)
27293d8817e4Smiod      bfd *abfd;
27303d8817e4Smiod      const PTR s;
27313d8817e4Smiod      struct internal_ldrel *dst;
27323d8817e4Smiod {
27333d8817e4Smiod   const struct external_ldrel *src = (const struct external_ldrel *) s;
27343d8817e4Smiod 
27353d8817e4Smiod   dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
27363d8817e4Smiod   dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
27373d8817e4Smiod   dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
27383d8817e4Smiod   dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
27393d8817e4Smiod }
27403d8817e4Smiod 
27413d8817e4Smiod /* Swap out the ldrel structure.  */
27423d8817e4Smiod 
27433d8817e4Smiod static void
xcoff_swap_ldrel_out(abfd,src,d)27443d8817e4Smiod xcoff_swap_ldrel_out (abfd, src, d)
27453d8817e4Smiod      bfd *abfd;
27463d8817e4Smiod      const struct internal_ldrel *src;
27473d8817e4Smiod      PTR d;
27483d8817e4Smiod {
27493d8817e4Smiod   struct external_ldrel *dst = (struct external_ldrel *) d;
27503d8817e4Smiod 
27513d8817e4Smiod   bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
27523d8817e4Smiod   bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
27533d8817e4Smiod   bfd_put_16 (abfd, (bfd_vma) src->l_rtype, dst->l_rtype);
27543d8817e4Smiod   bfd_put_16 (abfd, (bfd_vma) src->l_rsecnm, dst->l_rsecnm);
27553d8817e4Smiod }
27563d8817e4Smiod 
27573d8817e4Smiod 
27583d8817e4Smiod bfd_boolean
xcoff_reloc_type_noop(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)27593d8817e4Smiod xcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto,
27603d8817e4Smiod 		       val, addend, relocation, contents)
27613d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
27623d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
27633d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
27643d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
27653d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
27663d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
27673d8817e4Smiod      bfd_vma val ATTRIBUTE_UNUSED;
27683d8817e4Smiod      bfd_vma addend ATTRIBUTE_UNUSED;
27693d8817e4Smiod      bfd_vma *relocation ATTRIBUTE_UNUSED;
27703d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
27713d8817e4Smiod {
27723d8817e4Smiod   return TRUE;
27733d8817e4Smiod }
27743d8817e4Smiod 
27753d8817e4Smiod bfd_boolean
xcoff_reloc_type_fail(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)27763d8817e4Smiod xcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto,
27773d8817e4Smiod 		       val, addend, relocation, contents)
27783d8817e4Smiod      bfd *input_bfd;
27793d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
27803d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
27813d8817e4Smiod      struct internal_reloc *rel;
27823d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
27833d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
27843d8817e4Smiod      bfd_vma val ATTRIBUTE_UNUSED;
27853d8817e4Smiod      bfd_vma addend ATTRIBUTE_UNUSED;
27863d8817e4Smiod      bfd_vma *relocation ATTRIBUTE_UNUSED;
27873d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
27883d8817e4Smiod {
27893d8817e4Smiod   (*_bfd_error_handler)
27903d8817e4Smiod     (_("%s: unsupported relocation type 0x%02x"),
27913d8817e4Smiod      bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
27923d8817e4Smiod   bfd_set_error (bfd_error_bad_value);
27933d8817e4Smiod   return FALSE;
27943d8817e4Smiod }
27953d8817e4Smiod 
27963d8817e4Smiod bfd_boolean
xcoff_reloc_type_pos(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)27973d8817e4Smiod xcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto,
27983d8817e4Smiod 		      val, addend, relocation, contents)
27993d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
28003d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
28013d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
28023d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
28033d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
28043d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
28053d8817e4Smiod      bfd_vma val;
28063d8817e4Smiod      bfd_vma addend;
28073d8817e4Smiod      bfd_vma *relocation;
28083d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
28093d8817e4Smiod {
28103d8817e4Smiod   *relocation = val + addend;
28113d8817e4Smiod   return TRUE;
28123d8817e4Smiod }
28133d8817e4Smiod 
28143d8817e4Smiod bfd_boolean
xcoff_reloc_type_neg(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)28153d8817e4Smiod xcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto,
28163d8817e4Smiod 		      val, addend, relocation, contents)
28173d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
28183d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
28193d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
28203d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
28213d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
28223d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
28233d8817e4Smiod      bfd_vma val;
28243d8817e4Smiod      bfd_vma addend;
28253d8817e4Smiod      bfd_vma *relocation;
28263d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
28273d8817e4Smiod {
28283d8817e4Smiod   *relocation = addend - val;
28293d8817e4Smiod   return TRUE;
28303d8817e4Smiod }
28313d8817e4Smiod 
28323d8817e4Smiod bfd_boolean
xcoff_reloc_type_rel(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)28333d8817e4Smiod xcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto,
28343d8817e4Smiod 		      val, addend, relocation, contents)
28353d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
28363d8817e4Smiod      asection *input_section;
28373d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
28383d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
28393d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
28403d8817e4Smiod      struct reloc_howto_struct *howto;
28413d8817e4Smiod      bfd_vma val;
28423d8817e4Smiod      bfd_vma addend;
28433d8817e4Smiod      bfd_vma *relocation;
28443d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
28453d8817e4Smiod {
28463d8817e4Smiod   howto->pc_relative = TRUE;
28473d8817e4Smiod 
28483d8817e4Smiod   /* A PC relative reloc includes the section address.  */
28493d8817e4Smiod   addend += input_section->vma;
28503d8817e4Smiod 
28513d8817e4Smiod   *relocation = val + addend;
28523d8817e4Smiod   *relocation -= (input_section->output_section->vma
28533d8817e4Smiod 		  + input_section->output_offset);
28543d8817e4Smiod   return TRUE;
28553d8817e4Smiod }
28563d8817e4Smiod 
28573d8817e4Smiod bfd_boolean
xcoff_reloc_type_toc(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)28583d8817e4Smiod xcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto,
28593d8817e4Smiod 		      val, addend, relocation, contents)
28603d8817e4Smiod      bfd *input_bfd;
28613d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
28623d8817e4Smiod      bfd *output_bfd;
28633d8817e4Smiod      struct internal_reloc *rel;
28643d8817e4Smiod      struct internal_syment *sym;
28653d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
28663d8817e4Smiod      bfd_vma val;
28673d8817e4Smiod      bfd_vma addend ATTRIBUTE_UNUSED;
28683d8817e4Smiod      bfd_vma *relocation;
28693d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
28703d8817e4Smiod {
28713d8817e4Smiod   struct xcoff_link_hash_entry *h;
28723d8817e4Smiod 
28733d8817e4Smiod   if (0 > rel->r_symndx)
28743d8817e4Smiod     return FALSE;
28753d8817e4Smiod 
28763d8817e4Smiod   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
28773d8817e4Smiod 
28783d8817e4Smiod   if (h != NULL && h->smclas != XMC_TD)
28793d8817e4Smiod     {
28803d8817e4Smiod       if (h->toc_section == NULL)
28813d8817e4Smiod 	{
28823d8817e4Smiod 	  (*_bfd_error_handler)
28833d8817e4Smiod 	    (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
28843d8817e4Smiod 	     bfd_get_filename (input_bfd), rel->r_vaddr,
28853d8817e4Smiod 	     h->root.root.string);
28863d8817e4Smiod 	  bfd_set_error (bfd_error_bad_value);
28873d8817e4Smiod 	  return FALSE;
28883d8817e4Smiod 	}
28893d8817e4Smiod 
28903d8817e4Smiod       BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
28913d8817e4Smiod       val = (h->toc_section->output_section->vma
28923d8817e4Smiod 	      + h->toc_section->output_offset);
28933d8817e4Smiod     }
28943d8817e4Smiod 
28953d8817e4Smiod   *relocation = ((val - xcoff_data (output_bfd)->toc)
28963d8817e4Smiod 		 - (sym->n_value - xcoff_data (input_bfd)->toc));
28973d8817e4Smiod   return TRUE;
28983d8817e4Smiod }
28993d8817e4Smiod 
29003d8817e4Smiod bfd_boolean
xcoff_reloc_type_ba(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)29013d8817e4Smiod xcoff_reloc_type_ba (input_bfd, input_section, output_bfd, rel, sym, howto,
29023d8817e4Smiod 		     val, addend, relocation, contents)
29033d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
29043d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
29053d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
29063d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
29073d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
29083d8817e4Smiod      struct reloc_howto_struct *howto;
29093d8817e4Smiod      bfd_vma val;
29103d8817e4Smiod      bfd_vma addend;
29113d8817e4Smiod      bfd_vma *relocation;
29123d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
29133d8817e4Smiod {
29143d8817e4Smiod   howto->src_mask &= ~3;
29153d8817e4Smiod   howto->dst_mask = howto->src_mask;
29163d8817e4Smiod 
29173d8817e4Smiod   *relocation = val + addend;
29183d8817e4Smiod 
29193d8817e4Smiod   return TRUE;
29203d8817e4Smiod }
29213d8817e4Smiod 
29223d8817e4Smiod static bfd_boolean
xcoff_reloc_type_br(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)29233d8817e4Smiod xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
29243d8817e4Smiod 		     val, addend, relocation, contents)
29253d8817e4Smiod      bfd *input_bfd;
29263d8817e4Smiod      asection *input_section;
29273d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
29283d8817e4Smiod      struct internal_reloc *rel;
29293d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
29303d8817e4Smiod      struct reloc_howto_struct *howto;
29313d8817e4Smiod      bfd_vma val;
29323d8817e4Smiod      bfd_vma addend;
29333d8817e4Smiod      bfd_vma *relocation;
29343d8817e4Smiod      bfd_byte *contents;
29353d8817e4Smiod {
29363d8817e4Smiod   struct xcoff_link_hash_entry *h;
29373d8817e4Smiod 
29383d8817e4Smiod   if (0 > rel->r_symndx)
29393d8817e4Smiod     return FALSE;
29403d8817e4Smiod 
29413d8817e4Smiod   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
29423d8817e4Smiod 
29433d8817e4Smiod   /* If we see an R_BR or R_RBR reloc which is jumping to global
29443d8817e4Smiod      linkage code, and it is followed by an appropriate cror nop
29453d8817e4Smiod      instruction, we replace the cror with lwz r2,20(r1).  This
29463d8817e4Smiod      restores the TOC after the glink code.  Contrariwise, if the
29473d8817e4Smiod      call is followed by a lwz r2,20(r1), but the call is not
29483d8817e4Smiod      going to global linkage code, we can replace the load with a
29493d8817e4Smiod      cror.  */
29503d8817e4Smiod   if (NULL != h
29513d8817e4Smiod       && bfd_link_hash_defined == h->root.type
29523d8817e4Smiod       && rel->r_vaddr - input_section->vma + 8 <= input_section->size)
29533d8817e4Smiod     {
29543d8817e4Smiod       bfd_byte *pnext;
29553d8817e4Smiod       unsigned long next;
29563d8817e4Smiod 
29573d8817e4Smiod       pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
29583d8817e4Smiod       next = bfd_get_32 (input_bfd, pnext);
29593d8817e4Smiod 
29603d8817e4Smiod       /* The _ptrgl function is magic.  It is used by the AIX
29613d8817e4Smiod 	 compiler to call a function through a pointer.  */
29623d8817e4Smiod       if (h->smclas == XMC_GL || strcmp (h->root.root.string, "._ptrgl") == 0)
29633d8817e4Smiod 	{
29643d8817e4Smiod 	  if (next == 0x4def7b82			/* cror 15,15,15 */
29653d8817e4Smiod 	      || next == 0x4ffffb82			/* cror 31,31,31 */
29663d8817e4Smiod 	      || next == 0x60000000)			/* ori r0,r0,0 */
29673d8817e4Smiod 	    bfd_put_32 (input_bfd, 0x80410014, pnext);	/* lwz r1,20(r1) */
29683d8817e4Smiod 
29693d8817e4Smiod 	}
29703d8817e4Smiod       else
29713d8817e4Smiod 	{
29723d8817e4Smiod 	  if (next == 0x80410014)			/* lwz r1,20(r1) */
29733d8817e4Smiod 	    bfd_put_32 (input_bfd, 0x60000000, pnext);	/* ori r0,r0,0 */
29743d8817e4Smiod 	}
29753d8817e4Smiod     }
29763d8817e4Smiod   else if (NULL != h && bfd_link_hash_undefined == h->root.type)
29773d8817e4Smiod     {
29783d8817e4Smiod       /* Normally, this relocation is against a defined symbol.  In the
29793d8817e4Smiod 	 case where this is a partial link and the output section offset
29803d8817e4Smiod 	 is greater than 2^25, the linker will return an invalid error
29813d8817e4Smiod 	 message that the relocation has been truncated.  Yes it has been
29823d8817e4Smiod 	 truncated but no it not important.  For this case, disable the
29833d8817e4Smiod 	 overflow checking. */
29843d8817e4Smiod 
29853d8817e4Smiod       howto->complain_on_overflow = complain_overflow_dont;
29863d8817e4Smiod     }
29873d8817e4Smiod 
29883d8817e4Smiod   howto->pc_relative = TRUE;
29893d8817e4Smiod   howto->src_mask &= ~3;
29903d8817e4Smiod   howto->dst_mask = howto->src_mask;
29913d8817e4Smiod 
29923d8817e4Smiod   /* A PC relative reloc includes the section address.  */
29933d8817e4Smiod   addend += input_section->vma;
29943d8817e4Smiod 
29953d8817e4Smiod   *relocation = val + addend;
29963d8817e4Smiod   *relocation -= (input_section->output_section->vma
29973d8817e4Smiod 		  + input_section->output_offset);
29983d8817e4Smiod   return TRUE;
29993d8817e4Smiod }
30003d8817e4Smiod 
30013d8817e4Smiod bfd_boolean
xcoff_reloc_type_crel(input_bfd,input_section,output_bfd,rel,sym,howto,val,addend,relocation,contents)30023d8817e4Smiod xcoff_reloc_type_crel (input_bfd, input_section, output_bfd, rel, sym, howto,
30033d8817e4Smiod 		       val, addend, relocation, contents)
30043d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
30053d8817e4Smiod      asection *input_section;
30063d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
30073d8817e4Smiod      struct internal_reloc *rel ATTRIBUTE_UNUSED;
30083d8817e4Smiod      struct internal_syment *sym ATTRIBUTE_UNUSED;
30093d8817e4Smiod      struct reloc_howto_struct *howto;
30103d8817e4Smiod      bfd_vma val ATTRIBUTE_UNUSED;
30113d8817e4Smiod      bfd_vma addend;
30123d8817e4Smiod      bfd_vma *relocation;
30133d8817e4Smiod      bfd_byte *contents ATTRIBUTE_UNUSED;
30143d8817e4Smiod {
30153d8817e4Smiod   howto->pc_relative = TRUE;
30163d8817e4Smiod   howto->src_mask &= ~3;
30173d8817e4Smiod   howto->dst_mask = howto->src_mask;
30183d8817e4Smiod 
30193d8817e4Smiod   /* A PC relative reloc includes the section address.  */
30203d8817e4Smiod   addend += input_section->vma;
30213d8817e4Smiod 
30223d8817e4Smiod   *relocation = val + addend;
30233d8817e4Smiod   *relocation -= (input_section->output_section->vma
30243d8817e4Smiod 		  + input_section->output_offset);
30253d8817e4Smiod   return TRUE;
30263d8817e4Smiod }
30273d8817e4Smiod 
30283d8817e4Smiod static bfd_boolean
xcoff_complain_overflow_dont_func(input_bfd,val,relocation,howto)30293d8817e4Smiod xcoff_complain_overflow_dont_func (input_bfd, val, relocation, howto)
30303d8817e4Smiod      bfd *input_bfd ATTRIBUTE_UNUSED;
30313d8817e4Smiod      bfd_vma val ATTRIBUTE_UNUSED;
30323d8817e4Smiod      bfd_vma relocation ATTRIBUTE_UNUSED;
30333d8817e4Smiod      struct reloc_howto_struct *howto ATTRIBUTE_UNUSED;
30343d8817e4Smiod {
30353d8817e4Smiod   return FALSE;
30363d8817e4Smiod }
30373d8817e4Smiod 
30383d8817e4Smiod static bfd_boolean
xcoff_complain_overflow_bitfield_func(input_bfd,val,relocation,howto)30393d8817e4Smiod xcoff_complain_overflow_bitfield_func (input_bfd, val, relocation, howto)
30403d8817e4Smiod      bfd *input_bfd;
30413d8817e4Smiod      bfd_vma val;
30423d8817e4Smiod      bfd_vma relocation;
30433d8817e4Smiod      struct reloc_howto_struct *howto;
30443d8817e4Smiod {
30453d8817e4Smiod   bfd_vma addrmask, fieldmask, signmask, ss;
30463d8817e4Smiod   bfd_vma a, b, sum;
30473d8817e4Smiod 
30483d8817e4Smiod   /* Get the values to be added together.  For signed and unsigned
30493d8817e4Smiod      relocations, we assume that all values should be truncated to
30503d8817e4Smiod      the size of an address.  For bitfields, all the bits matter.
30513d8817e4Smiod      See also bfd_check_overflow.  */
30523d8817e4Smiod   fieldmask = N_ONES (howto->bitsize);
30533d8817e4Smiod   addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask;
30543d8817e4Smiod   a = relocation;
30553d8817e4Smiod   b = val & howto->src_mask;
30563d8817e4Smiod 
30573d8817e4Smiod   /* Much like unsigned, except no trimming with addrmask.  In
30583d8817e4Smiod      addition, the sum overflows if there is a carry out of
30593d8817e4Smiod      the bfd_vma, i.e., the sum is less than either input
30603d8817e4Smiod      operand.  */
30613d8817e4Smiod   a >>= howto->rightshift;
30623d8817e4Smiod   b >>= howto->bitpos;
30633d8817e4Smiod 
30643d8817e4Smiod   /* Bitfields are sometimes used for signed numbers; for
30653d8817e4Smiod      example, a 13-bit field sometimes represents values in
30663d8817e4Smiod      0..8191 and sometimes represents values in -4096..4095.
30673d8817e4Smiod      If the field is signed and a is -4095 (0x1001) and b is
30683d8817e4Smiod      -1 (0x1fff), the sum is -4096 (0x1000), but (0x1001 +
30693d8817e4Smiod      0x1fff is 0x3000).  It's not clear how to handle this
30703d8817e4Smiod      everywhere, since there is not way to know how many bits
30713d8817e4Smiod      are significant in the relocation, but the original code
30723d8817e4Smiod      assumed that it was fully sign extended, and we will keep
30733d8817e4Smiod      that assumption.  */
30743d8817e4Smiod   signmask = (fieldmask >> 1) + 1;
30753d8817e4Smiod 
30763d8817e4Smiod   if ((a & ~ fieldmask) != 0)
30773d8817e4Smiod     {
30783d8817e4Smiod       /* Some bits out of the field are set.  This might not
30793d8817e4Smiod 	 be a problem: if this is a signed bitfield, it is OK
30803d8817e4Smiod 	 iff all the high bits are set, including the sign
30813d8817e4Smiod 	 bit.  We'll try setting all but the most significant
30823d8817e4Smiod 	 bit in the original relocation value: if this is all
30833d8817e4Smiod 	 ones, we are OK, assuming a signed bitfield.  */
30843d8817e4Smiod       ss = (signmask << howto->rightshift) - 1;
30853d8817e4Smiod       if ((ss | relocation) != ~ (bfd_vma) 0)
30863d8817e4Smiod 	return TRUE;
30873d8817e4Smiod       a &= fieldmask;
30883d8817e4Smiod     }
30893d8817e4Smiod 
30903d8817e4Smiod   /* We just assume (b & ~ fieldmask) == 0.  */
30913d8817e4Smiod 
30923d8817e4Smiod   /* We explicitly permit wrap around if this relocation
30933d8817e4Smiod      covers the high bit of an address.  The Linux kernel
30943d8817e4Smiod      relies on it, and it is the only way to write assembler
30953d8817e4Smiod      code which can run when loaded at a location 0x80000000
30963d8817e4Smiod      away from the location at which it is linked.  */
30973d8817e4Smiod   if (howto->bitsize + howto->rightshift
30983d8817e4Smiod       == bfd_arch_bits_per_address (input_bfd))
30993d8817e4Smiod     return FALSE;
31003d8817e4Smiod 
31013d8817e4Smiod   sum = a + b;
31023d8817e4Smiod   if (sum < a || (sum & ~ fieldmask) != 0)
31033d8817e4Smiod     {
31043d8817e4Smiod       /* There was a carry out, or the field overflow.  Test
31053d8817e4Smiod 	 for signed operands again.  Here is the overflow test
31063d8817e4Smiod 	 is as for complain_overflow_signed.  */
31073d8817e4Smiod       if (((~ (a ^ b)) & (a ^ sum)) & signmask)
31083d8817e4Smiod 	return TRUE;
31093d8817e4Smiod     }
31103d8817e4Smiod 
31113d8817e4Smiod   return FALSE;
31123d8817e4Smiod }
31133d8817e4Smiod 
31143d8817e4Smiod static bfd_boolean
xcoff_complain_overflow_signed_func(input_bfd,val,relocation,howto)31153d8817e4Smiod xcoff_complain_overflow_signed_func (input_bfd, val, relocation, howto)
31163d8817e4Smiod      bfd *input_bfd;
31173d8817e4Smiod      bfd_vma val;
31183d8817e4Smiod      bfd_vma relocation;
31193d8817e4Smiod      struct reloc_howto_struct *howto;
31203d8817e4Smiod {
31213d8817e4Smiod   bfd_vma addrmask, fieldmask, signmask, ss;
31223d8817e4Smiod   bfd_vma a, b, sum;
31233d8817e4Smiod 
31243d8817e4Smiod   /* Get the values to be added together.  For signed and unsigned
31253d8817e4Smiod      relocations, we assume that all values should be truncated to
31263d8817e4Smiod      the size of an address.  For bitfields, all the bits matter.
31273d8817e4Smiod      See also bfd_check_overflow.  */
31283d8817e4Smiod   fieldmask = N_ONES (howto->bitsize);
31293d8817e4Smiod   addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask;
31303d8817e4Smiod   a = relocation;
31313d8817e4Smiod   b = val & howto->src_mask;
31323d8817e4Smiod 
31333d8817e4Smiod   a = (a & addrmask) >> howto->rightshift;
31343d8817e4Smiod 
31353d8817e4Smiod   /* If any sign bits are set, all sign bits must be set.
31363d8817e4Smiod      That is, A must be a valid negative address after
31373d8817e4Smiod      shifting.  */
31383d8817e4Smiod   signmask = ~ (fieldmask >> 1);
31393d8817e4Smiod   ss = a & signmask;
31403d8817e4Smiod   if (ss != 0 && ss != ((addrmask >> howto->rightshift) & signmask))
31413d8817e4Smiod     return TRUE;
31423d8817e4Smiod 
31433d8817e4Smiod   /* We only need this next bit of code if the sign bit of B
31443d8817e4Smiod      is below the sign bit of A.  This would only happen if
31453d8817e4Smiod      SRC_MASK had fewer bits than BITSIZE.  Note that if
31463d8817e4Smiod      SRC_MASK has more bits than BITSIZE, we can get into
31473d8817e4Smiod      trouble; we would need to verify that B is in range, as
31483d8817e4Smiod      we do for A above.  */
31493d8817e4Smiod   signmask = ((~ howto->src_mask) >> 1) & howto->src_mask;
31503d8817e4Smiod   if ((b & signmask) != 0)
31513d8817e4Smiod     {
31523d8817e4Smiod       /* Set all the bits above the sign bit.  */
31533d8817e4Smiod       b -= signmask <<= 1;
31543d8817e4Smiod     }
31553d8817e4Smiod 
31563d8817e4Smiod   b = (b & addrmask) >> howto->bitpos;
31573d8817e4Smiod 
31583d8817e4Smiod   /* Now we can do the addition.  */
31593d8817e4Smiod   sum = a + b;
31603d8817e4Smiod 
31613d8817e4Smiod   /* See if the result has the correct sign.  Bits above the
31623d8817e4Smiod      sign bit are junk now; ignore them.  If the sum is
31633d8817e4Smiod      positive, make sure we did not have all negative inputs;
31643d8817e4Smiod      if the sum is negative, make sure we did not have all
31653d8817e4Smiod      positive inputs.  The test below looks only at the sign
31663d8817e4Smiod      bits, and it really just
31673d8817e4Smiod      SIGN (A) == SIGN (B) && SIGN (A) != SIGN (SUM)
31683d8817e4Smiod   */
31693d8817e4Smiod   signmask = (fieldmask >> 1) + 1;
31703d8817e4Smiod   if (((~ (a ^ b)) & (a ^ sum)) & signmask)
31713d8817e4Smiod     return TRUE;
31723d8817e4Smiod 
31733d8817e4Smiod   return FALSE;
31743d8817e4Smiod }
31753d8817e4Smiod 
31763d8817e4Smiod static bfd_boolean
xcoff_complain_overflow_unsigned_func(input_bfd,val,relocation,howto)31773d8817e4Smiod xcoff_complain_overflow_unsigned_func (input_bfd, val, relocation, howto)
31783d8817e4Smiod      bfd *input_bfd;
31793d8817e4Smiod      bfd_vma val;
31803d8817e4Smiod      bfd_vma relocation;
31813d8817e4Smiod      struct reloc_howto_struct *howto;
31823d8817e4Smiod {
31833d8817e4Smiod   bfd_vma addrmask, fieldmask;
31843d8817e4Smiod   bfd_vma a, b, sum;
31853d8817e4Smiod 
31863d8817e4Smiod   /* Get the values to be added together.  For signed and unsigned
31873d8817e4Smiod      relocations, we assume that all values should be truncated to
31883d8817e4Smiod      the size of an address.  For bitfields, all the bits matter.
31893d8817e4Smiod      See also bfd_check_overflow.  */
31903d8817e4Smiod   fieldmask = N_ONES (howto->bitsize);
31913d8817e4Smiod   addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask;
31923d8817e4Smiod   a = relocation;
31933d8817e4Smiod   b = val & howto->src_mask;
31943d8817e4Smiod 
31953d8817e4Smiod   /* Checking for an unsigned overflow is relatively easy:
31963d8817e4Smiod      trim the addresses and add, and trim the result as well.
31973d8817e4Smiod      Overflow is normally indicated when the result does not
31983d8817e4Smiod      fit in the field.  However, we also need to consider the
31993d8817e4Smiod      case when, e.g., fieldmask is 0x7fffffff or smaller, an
32003d8817e4Smiod      input is 0x80000000, and bfd_vma is only 32 bits; then we
32013d8817e4Smiod      will get sum == 0, but there is an overflow, since the
32023d8817e4Smiod      inputs did not fit in the field.  Instead of doing a
32033d8817e4Smiod      separate test, we can check for this by or-ing in the
32043d8817e4Smiod      operands when testing for the sum overflowing its final
32053d8817e4Smiod      field.  */
32063d8817e4Smiod   a = (a & addrmask) >> howto->rightshift;
32073d8817e4Smiod   b = (b & addrmask) >> howto->bitpos;
32083d8817e4Smiod   sum = (a + b) & addrmask;
32093d8817e4Smiod   if ((a | b | sum) & ~ fieldmask)
32103d8817e4Smiod     return TRUE;
32113d8817e4Smiod 
32123d8817e4Smiod   return FALSE;
32133d8817e4Smiod }
32143d8817e4Smiod 
32153d8817e4Smiod /* This is the relocation function for the RS/6000/POWER/PowerPC.
32163d8817e4Smiod    This is currently the only processor which uses XCOFF; I hope that
32173d8817e4Smiod    will never change.
32183d8817e4Smiod 
32193d8817e4Smiod    I took the relocation type definitions from two documents:
32203d8817e4Smiod    the PowerPC AIX Version 4 Application Binary Interface, First
32213d8817e4Smiod    Edition (April 1992), and the PowerOpen ABI, Big-Endian
32223d8817e4Smiod    32-Bit Hardware Implementation (June 30, 1994).  Differences
32233d8817e4Smiod    between the documents are noted below.
32243d8817e4Smiod 
32253d8817e4Smiod    Unsupported r_type's
32263d8817e4Smiod 
32273d8817e4Smiod    R_RTB:
32283d8817e4Smiod    R_RRTBI:
32293d8817e4Smiod    R_RRTBA:
32303d8817e4Smiod 
32313d8817e4Smiod    These relocs are defined by the PowerPC ABI to be
32323d8817e4Smiod    relative branches which use half of the difference
32333d8817e4Smiod    between the symbol and the program counter.  I can't
32343d8817e4Smiod    quite figure out when this is useful.  These relocs are
32353d8817e4Smiod    not defined by the PowerOpen ABI.
32363d8817e4Smiod 
32373d8817e4Smiod    Supported r_type's
32383d8817e4Smiod 
32393d8817e4Smiod    R_POS:
32403d8817e4Smiod    Simple positive relocation.
32413d8817e4Smiod 
32423d8817e4Smiod    R_NEG:
32433d8817e4Smiod    Simple negative relocation.
32443d8817e4Smiod 
32453d8817e4Smiod    R_REL:
32463d8817e4Smiod    Simple PC relative relocation.
32473d8817e4Smiod 
32483d8817e4Smiod    R_TOC:
32493d8817e4Smiod    TOC relative relocation.  The value in the instruction in
32503d8817e4Smiod    the input file is the offset from the input file TOC to
32513d8817e4Smiod    the desired location.  We want the offset from the final
32523d8817e4Smiod    TOC to the desired location.  We have:
32533d8817e4Smiod    isym = iTOC + in
32543d8817e4Smiod    iinsn = in + o
32553d8817e4Smiod    osym = oTOC + on
32563d8817e4Smiod    oinsn = on + o
32573d8817e4Smiod    so we must change insn by on - in.
32583d8817e4Smiod 
32593d8817e4Smiod    R_GL:
32603d8817e4Smiod    GL linkage relocation.  The value of this relocation
32613d8817e4Smiod    is the address of the entry in the TOC section.
32623d8817e4Smiod 
32633d8817e4Smiod    R_TCL:
32643d8817e4Smiod    Local object TOC address.  I can't figure out the
32653d8817e4Smiod    difference between this and case R_GL.
32663d8817e4Smiod 
32673d8817e4Smiod    R_TRL:
32683d8817e4Smiod    TOC relative relocation.  A TOC relative load instruction
32693d8817e4Smiod    which may be changed to a load address instruction.
32703d8817e4Smiod    FIXME: We don't currently implement this optimization.
32713d8817e4Smiod 
32723d8817e4Smiod    R_TRLA:
32733d8817e4Smiod    TOC relative relocation.  This is a TOC relative load
32743d8817e4Smiod    address instruction which may be changed to a load
32753d8817e4Smiod    instruction.  FIXME: I don't know if this is the correct
32763d8817e4Smiod    implementation.
32773d8817e4Smiod 
32783d8817e4Smiod    R_BA:
32793d8817e4Smiod    Absolute branch.  We don't want to mess with the lower
32803d8817e4Smiod    two bits of the instruction.
32813d8817e4Smiod 
32823d8817e4Smiod    R_CAI:
32833d8817e4Smiod    The PowerPC ABI defines this as an absolute call which
32843d8817e4Smiod    may be modified to become a relative call.  The PowerOpen
32853d8817e4Smiod    ABI does not define this relocation type.
32863d8817e4Smiod 
32873d8817e4Smiod    R_RBA:
32883d8817e4Smiod    Absolute branch which may be modified to become a
32893d8817e4Smiod    relative branch.
32903d8817e4Smiod 
32913d8817e4Smiod    R_RBAC:
32923d8817e4Smiod    The PowerPC ABI defines this as an absolute branch to a
32933d8817e4Smiod    fixed address which may be modified to an absolute branch
32943d8817e4Smiod    to a symbol.  The PowerOpen ABI does not define this
32953d8817e4Smiod    relocation type.
32963d8817e4Smiod 
32973d8817e4Smiod    R_RBRC:
32983d8817e4Smiod    The PowerPC ABI defines this as an absolute branch to a
32993d8817e4Smiod    fixed address which may be modified to a relative branch.
33003d8817e4Smiod    The PowerOpen ABI does not define this relocation type.
33013d8817e4Smiod 
33023d8817e4Smiod    R_BR:
33033d8817e4Smiod    Relative branch.  We don't want to mess with the lower
33043d8817e4Smiod    two bits of the instruction.
33053d8817e4Smiod 
33063d8817e4Smiod    R_CREL:
33073d8817e4Smiod    The PowerPC ABI defines this as a relative call which may
33083d8817e4Smiod    be modified to become an absolute call.  The PowerOpen
33093d8817e4Smiod    ABI does not define this relocation type.
33103d8817e4Smiod 
33113d8817e4Smiod    R_RBR:
33123d8817e4Smiod    A relative branch which may be modified to become an
33133d8817e4Smiod    absolute branch.  FIXME: We don't implement this,
33143d8817e4Smiod    although we should for symbols of storage mapping class
33153d8817e4Smiod    XMC_XO.
33163d8817e4Smiod 
33173d8817e4Smiod    R_RL:
33183d8817e4Smiod    The PowerPC AIX ABI describes this as a load which may be
33193d8817e4Smiod    changed to a load address.  The PowerOpen ABI says this
33203d8817e4Smiod    is the same as case R_POS.
33213d8817e4Smiod 
33223d8817e4Smiod    R_RLA:
33233d8817e4Smiod    The PowerPC AIX ABI describes this as a load address
33243d8817e4Smiod    which may be changed to a load.  The PowerOpen ABI says
33253d8817e4Smiod    this is the same as R_POS.
33263d8817e4Smiod */
33273d8817e4Smiod 
33283d8817e4Smiod bfd_boolean
xcoff_ppc_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,syms,sections)33293d8817e4Smiod xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
33303d8817e4Smiod 			    input_section, contents, relocs, syms,
33313d8817e4Smiod 			    sections)
33323d8817e4Smiod      bfd *output_bfd;
33333d8817e4Smiod      struct bfd_link_info *info;
33343d8817e4Smiod      bfd *input_bfd;
33353d8817e4Smiod      asection *input_section;
33363d8817e4Smiod      bfd_byte *contents;
33373d8817e4Smiod      struct internal_reloc *relocs;
33383d8817e4Smiod      struct internal_syment *syms;
33393d8817e4Smiod      asection **sections;
33403d8817e4Smiod {
33413d8817e4Smiod   struct internal_reloc *rel;
33423d8817e4Smiod   struct internal_reloc *relend;
33433d8817e4Smiod 
33443d8817e4Smiod   rel = relocs;
33453d8817e4Smiod   relend = rel + input_section->reloc_count;
33463d8817e4Smiod   for (; rel < relend; rel++)
33473d8817e4Smiod     {
33483d8817e4Smiod       long symndx;
33493d8817e4Smiod       struct xcoff_link_hash_entry *h;
33503d8817e4Smiod       struct internal_syment *sym;
33513d8817e4Smiod       bfd_vma addend;
33523d8817e4Smiod       bfd_vma val;
33533d8817e4Smiod       struct reloc_howto_struct howto;
33543d8817e4Smiod       bfd_vma relocation;
33553d8817e4Smiod       bfd_vma value_to_relocate;
33563d8817e4Smiod       bfd_vma address;
33573d8817e4Smiod       bfd_byte *location;
33583d8817e4Smiod 
33593d8817e4Smiod       /* Relocation type R_REF is a special relocation type which is
33603d8817e4Smiod 	 merely used to prevent garbage collection from occurring for
33613d8817e4Smiod 	 the csect including the symbol which it references.  */
33623d8817e4Smiod       if (rel->r_type == R_REF)
33633d8817e4Smiod 	continue;
33643d8817e4Smiod 
33653d8817e4Smiod       /* howto */
33663d8817e4Smiod       howto.type = rel->r_type;
33673d8817e4Smiod       howto.rightshift = 0;
33683d8817e4Smiod       howto.bitsize = (rel->r_size & 0x1f) + 1;
33693d8817e4Smiod       howto.size = howto.bitsize > 16 ? 2 : 1;
33703d8817e4Smiod       howto.pc_relative = FALSE;
33713d8817e4Smiod       howto.bitpos = 0;
33723d8817e4Smiod       howto.complain_on_overflow = (rel->r_size & 0x80
33733d8817e4Smiod 				    ? complain_overflow_signed
33743d8817e4Smiod 				    : complain_overflow_bitfield);
33753d8817e4Smiod       howto.special_function = NULL;
33763d8817e4Smiod       howto.name = "internal";
33773d8817e4Smiod       howto.partial_inplace = TRUE;
33783d8817e4Smiod       howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
33793d8817e4Smiod       howto.pcrel_offset = FALSE;
33803d8817e4Smiod 
33813d8817e4Smiod       /* symbol */
33823d8817e4Smiod       val = 0;
33833d8817e4Smiod       addend = 0;
33843d8817e4Smiod       h = NULL;
33853d8817e4Smiod       sym = NULL;
33863d8817e4Smiod       symndx = rel->r_symndx;
33873d8817e4Smiod 
33883d8817e4Smiod       if (-1 != symndx)
33893d8817e4Smiod 	{
33903d8817e4Smiod 	  asection *sec;
33913d8817e4Smiod 
33923d8817e4Smiod 	  h = obj_xcoff_sym_hashes (input_bfd)[symndx];
33933d8817e4Smiod 	  sym = syms + symndx;
33943d8817e4Smiod 	  addend = - sym->n_value;
33953d8817e4Smiod 
33963d8817e4Smiod 	  if (NULL == h)
33973d8817e4Smiod 	    {
33983d8817e4Smiod 	      sec = sections[symndx];
33993d8817e4Smiod 	      /* Hack to make sure we use the right TOC anchor value
34003d8817e4Smiod 		 if this reloc is against the TOC anchor.  */
34013d8817e4Smiod 	      if (sec->name[3] == '0'
34023d8817e4Smiod 		  && strcmp (sec->name, ".tc0") == 0)
34033d8817e4Smiod 		val = xcoff_data (output_bfd)->toc;
34043d8817e4Smiod 	      else
34053d8817e4Smiod 		val = (sec->output_section->vma
34063d8817e4Smiod 		       + sec->output_offset
34073d8817e4Smiod 		       + sym->n_value
34083d8817e4Smiod 		       - sec->vma);
34093d8817e4Smiod 	    }
34103d8817e4Smiod 	  else
34113d8817e4Smiod 	    {
34123d8817e4Smiod 	      if (h->root.type == bfd_link_hash_defined
34133d8817e4Smiod 		  || h->root.type == bfd_link_hash_defweak)
34143d8817e4Smiod 		{
34153d8817e4Smiod 		  sec = h->root.u.def.section;
34163d8817e4Smiod 		  val = (h->root.u.def.value
34173d8817e4Smiod 			 + sec->output_section->vma
34183d8817e4Smiod 			 + sec->output_offset);
34193d8817e4Smiod 		}
34203d8817e4Smiod 	      else if (h->root.type == bfd_link_hash_common)
34213d8817e4Smiod 		{
34223d8817e4Smiod 		  sec = h->root.u.c.p->section;
34233d8817e4Smiod 		  val = (sec->output_section->vma
34243d8817e4Smiod 			 + sec->output_offset);
34253d8817e4Smiod 
34263d8817e4Smiod 		}
34273d8817e4Smiod 	      else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
34283d8817e4Smiod 		       && ! info->relocatable)
34293d8817e4Smiod 		{
34303d8817e4Smiod 		  if (! ((*info->callbacks->undefined_symbol)
34313d8817e4Smiod 			 (info, h->root.root.string, input_bfd, input_section,
34323d8817e4Smiod 			  rel->r_vaddr - input_section->vma, TRUE)))
34333d8817e4Smiod 		    return FALSE;
34343d8817e4Smiod 
34353d8817e4Smiod 		  /* Don't try to process the reloc.  It can't help, and
34363d8817e4Smiod 		     it may generate another error.  */
34373d8817e4Smiod 		  continue;
34383d8817e4Smiod 		}
34393d8817e4Smiod 	    }
34403d8817e4Smiod 	}
34413d8817e4Smiod 
34423d8817e4Smiod       if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
34433d8817e4Smiod 	  || !((*xcoff_calculate_relocation[rel->r_type])
34443d8817e4Smiod 	       (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
34453d8817e4Smiod 		addend, &relocation, contents)))
34463d8817e4Smiod 	return FALSE;
34473d8817e4Smiod 
34483d8817e4Smiod       /* address */
34493d8817e4Smiod       address = rel->r_vaddr - input_section->vma;
34503d8817e4Smiod       location = contents + address;
34513d8817e4Smiod 
34523d8817e4Smiod       if (address > input_section->size)
34533d8817e4Smiod 	abort ();
34543d8817e4Smiod 
34553d8817e4Smiod       /* Get the value we are going to relocate.  */
34563d8817e4Smiod       if (1 == howto.size)
34573d8817e4Smiod 	value_to_relocate = bfd_get_16 (input_bfd, location);
34583d8817e4Smiod       else
34593d8817e4Smiod 	value_to_relocate = bfd_get_32 (input_bfd, location);
34603d8817e4Smiod 
34613d8817e4Smiod       /* overflow.
34623d8817e4Smiod 
34633d8817e4Smiod 	 FIXME: We may drop bits during the addition
34643d8817e4Smiod 	 which we don't check for.  We must either check at every single
34653d8817e4Smiod 	 operation, which would be tedious, or we must do the computations
34663d8817e4Smiod 	 in a type larger than bfd_vma, which would be inefficient.  */
34673d8817e4Smiod 
34683d8817e4Smiod       if ((unsigned int) howto.complain_on_overflow
34693d8817e4Smiod 	  >= XCOFF_MAX_COMPLAIN_OVERFLOW)
34703d8817e4Smiod 	abort ();
34713d8817e4Smiod 
34723d8817e4Smiod       if (((*xcoff_complain_overflow[howto.complain_on_overflow])
34733d8817e4Smiod 	   (input_bfd, value_to_relocate, relocation, &howto)))
34743d8817e4Smiod 	{
34753d8817e4Smiod 	  const char *name;
34763d8817e4Smiod 	  char buf[SYMNMLEN + 1];
34773d8817e4Smiod 	  char reloc_type_name[10];
34783d8817e4Smiod 
34793d8817e4Smiod 	  if (symndx == -1)
34803d8817e4Smiod 	    {
34813d8817e4Smiod 	      name = "*ABS*";
34823d8817e4Smiod 	    }
34833d8817e4Smiod 	  else if (h != NULL)
34843d8817e4Smiod 	    {
34853d8817e4Smiod 	      name = NULL;
34863d8817e4Smiod 	    }
34873d8817e4Smiod 	  else
34883d8817e4Smiod 	    {
34893d8817e4Smiod 	      name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
34903d8817e4Smiod 	      if (name == NULL)
34913d8817e4Smiod 		name = "UNKNOWN";
34923d8817e4Smiod 	    }
34933d8817e4Smiod 	  sprintf (reloc_type_name, "0x%02x", rel->r_type);
34943d8817e4Smiod 
34953d8817e4Smiod 	  if (! ((*info->callbacks->reloc_overflow)
34963d8817e4Smiod 		 (info, (h ? &h->root : NULL), name, reloc_type_name,
34973d8817e4Smiod 		  (bfd_vma) 0, input_bfd, input_section,
34983d8817e4Smiod 		  rel->r_vaddr - input_section->vma)))
34993d8817e4Smiod 	    return FALSE;
35003d8817e4Smiod 	}
35013d8817e4Smiod 
35023d8817e4Smiod       /* Add RELOCATION to the right bits of VALUE_TO_RELOCATE.  */
35033d8817e4Smiod       value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
35043d8817e4Smiod 			   | (((value_to_relocate & howto.src_mask)
35053d8817e4Smiod 			       + relocation) & howto.dst_mask));
35063d8817e4Smiod 
35073d8817e4Smiod       /* Put the value back in the object file.  */
35083d8817e4Smiod       if (1 == howto.size)
35093d8817e4Smiod 	bfd_put_16 (input_bfd, value_to_relocate, location);
35103d8817e4Smiod       else
35113d8817e4Smiod 	bfd_put_32 (input_bfd, value_to_relocate, location);
35123d8817e4Smiod     }
35133d8817e4Smiod 
35143d8817e4Smiod   return TRUE;
35153d8817e4Smiod }
35163d8817e4Smiod 
35173d8817e4Smiod static bfd_boolean
_bfd_xcoff_put_ldsymbol_name(abfd,ldinfo,ldsym,name)35183d8817e4Smiod _bfd_xcoff_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
35193d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
35203d8817e4Smiod 	 struct xcoff_loader_info *ldinfo;
35213d8817e4Smiod 	 struct internal_ldsym *ldsym;
35223d8817e4Smiod 	 const char *name;
35233d8817e4Smiod {
35243d8817e4Smiod   size_t len;
35253d8817e4Smiod   len = strlen (name);
35263d8817e4Smiod 
35273d8817e4Smiod   if (len <= SYMNMLEN)
35283d8817e4Smiod     strncpy (ldsym->_l._l_name, name, SYMNMLEN);
35293d8817e4Smiod   else
35303d8817e4Smiod     {
35313d8817e4Smiod       if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
35323d8817e4Smiod 	{
35333d8817e4Smiod 	  bfd_size_type newalc;
35343d8817e4Smiod 	  char *newstrings;
35353d8817e4Smiod 
35363d8817e4Smiod 	  newalc = ldinfo->string_alc * 2;
35373d8817e4Smiod 	  if (newalc == 0)
35383d8817e4Smiod 	    newalc = 32;
35393d8817e4Smiod 	  while (ldinfo->string_size + len + 3 > newalc)
35403d8817e4Smiod 	    newalc *= 2;
35413d8817e4Smiod 
35423d8817e4Smiod 	  newstrings = bfd_realloc (ldinfo->strings, newalc);
35433d8817e4Smiod 	  if (newstrings == NULL)
35443d8817e4Smiod 	    {
35453d8817e4Smiod 	      ldinfo->failed = TRUE;
35463d8817e4Smiod 	      return FALSE;
35473d8817e4Smiod 	    }
35483d8817e4Smiod 	  ldinfo->string_alc = newalc;
35493d8817e4Smiod 	  ldinfo->strings = newstrings;
35503d8817e4Smiod 	}
35513d8817e4Smiod 
35523d8817e4Smiod       bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1),
35533d8817e4Smiod 		  ldinfo->strings + ldinfo->string_size);
35543d8817e4Smiod       strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
35553d8817e4Smiod       ldsym->_l._l_l._l_zeroes = 0;
35563d8817e4Smiod       ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
35573d8817e4Smiod       ldinfo->string_size += len + 3;
35583d8817e4Smiod     }
35593d8817e4Smiod 
35603d8817e4Smiod   return TRUE;
35613d8817e4Smiod }
35623d8817e4Smiod 
35633d8817e4Smiod static bfd_boolean
_bfd_xcoff_put_symbol_name(bfd * abfd,struct bfd_strtab_hash * strtab,struct internal_syment * sym,const char * name)35643d8817e4Smiod _bfd_xcoff_put_symbol_name (bfd *abfd, struct bfd_strtab_hash *strtab,
35653d8817e4Smiod 			    struct internal_syment *sym,
35663d8817e4Smiod 			    const char *name)
35673d8817e4Smiod {
35683d8817e4Smiod   if (strlen (name) <= SYMNMLEN)
35693d8817e4Smiod     {
35703d8817e4Smiod       strncpy (sym->_n._n_name, name, SYMNMLEN);
35713d8817e4Smiod     }
35723d8817e4Smiod   else
35733d8817e4Smiod     {
35743d8817e4Smiod       bfd_boolean hash;
35753d8817e4Smiod       bfd_size_type indx;
35763d8817e4Smiod 
35773d8817e4Smiod       hash = TRUE;
35783d8817e4Smiod       if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
35793d8817e4Smiod 	hash = FALSE;
35803d8817e4Smiod       indx = _bfd_stringtab_add (strtab, name, hash, FALSE);
35813d8817e4Smiod       if (indx == (bfd_size_type) -1)
35823d8817e4Smiod 	return FALSE;
35833d8817e4Smiod       sym->_n._n_n._n_zeroes = 0;
35843d8817e4Smiod       sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx;
35853d8817e4Smiod     }
35863d8817e4Smiod   return TRUE;
35873d8817e4Smiod }
35883d8817e4Smiod 
35893d8817e4Smiod static asection *
xcoff_create_csect_from_smclas(abfd,aux,symbol_name)35903d8817e4Smiod xcoff_create_csect_from_smclas (abfd, aux, symbol_name)
35913d8817e4Smiod      bfd *abfd;
35923d8817e4Smiod      union internal_auxent *aux;
35933d8817e4Smiod      const char *symbol_name;
35943d8817e4Smiod {
35953d8817e4Smiod   asection *return_value = NULL;
35963d8817e4Smiod 
35973d8817e4Smiod   /* .sv64 = x_smclas == 17
35983d8817e4Smiod      This is an invalid csect for 32 bit apps.  */
35993d8817e4Smiod   static const char *names[19] =
36003d8817e4Smiod   {
36013d8817e4Smiod     ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
36023d8817e4Smiod     ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
36033d8817e4Smiod     ".td", NULL, ".sv3264"
36043d8817e4Smiod   };
36053d8817e4Smiod 
36063d8817e4Smiod   if ((19 >= aux->x_csect.x_smclas)
36073d8817e4Smiod       && (NULL != names[aux->x_csect.x_smclas]))
36083d8817e4Smiod     {
36093d8817e4Smiod       return_value = bfd_make_section_anyway
36103d8817e4Smiod 	(abfd, names[aux->x_csect.x_smclas]);
36113d8817e4Smiod     }
36123d8817e4Smiod   else
36133d8817e4Smiod     {
36143d8817e4Smiod       (*_bfd_error_handler)
36153d8817e4Smiod 	(_("%B: symbol `%s' has unrecognized smclas %d"),
36163d8817e4Smiod 	 abfd, symbol_name, aux->x_csect.x_smclas);
36173d8817e4Smiod       bfd_set_error (bfd_error_bad_value);
36183d8817e4Smiod     }
36193d8817e4Smiod 
36203d8817e4Smiod   return return_value;
36213d8817e4Smiod }
36223d8817e4Smiod 
36233d8817e4Smiod static bfd_boolean
xcoff_is_lineno_count_overflow(abfd,value)36243d8817e4Smiod xcoff_is_lineno_count_overflow (abfd, value)
36253d8817e4Smiod     bfd *abfd ATTRIBUTE_UNUSED;
36263d8817e4Smiod 	bfd_vma value;
36273d8817e4Smiod {
36283d8817e4Smiod   if (0xffff <= value)
36293d8817e4Smiod     return TRUE;
36303d8817e4Smiod 
36313d8817e4Smiod   return FALSE;
36323d8817e4Smiod }
36333d8817e4Smiod 
36343d8817e4Smiod static bfd_boolean
xcoff_is_reloc_count_overflow(abfd,value)36353d8817e4Smiod xcoff_is_reloc_count_overflow (abfd, value)
36363d8817e4Smiod     bfd *abfd ATTRIBUTE_UNUSED;
36373d8817e4Smiod 	bfd_vma value;
36383d8817e4Smiod {
36393d8817e4Smiod   if (0xffff <= value)
36403d8817e4Smiod     return TRUE;
36413d8817e4Smiod 
36423d8817e4Smiod   return FALSE;
36433d8817e4Smiod }
36443d8817e4Smiod 
36453d8817e4Smiod static bfd_vma
xcoff_loader_symbol_offset(abfd,ldhdr)36463d8817e4Smiod xcoff_loader_symbol_offset (abfd, ldhdr)
36473d8817e4Smiod     bfd *abfd;
36483d8817e4Smiod     struct internal_ldhdr *ldhdr ATTRIBUTE_UNUSED;
36493d8817e4Smiod {
36503d8817e4Smiod   return bfd_xcoff_ldhdrsz (abfd);
36513d8817e4Smiod }
36523d8817e4Smiod 
36533d8817e4Smiod static bfd_vma
xcoff_loader_reloc_offset(abfd,ldhdr)36543d8817e4Smiod xcoff_loader_reloc_offset (abfd, ldhdr)
36553d8817e4Smiod     bfd *abfd;
36563d8817e4Smiod     struct internal_ldhdr *ldhdr;
36573d8817e4Smiod {
36583d8817e4Smiod   return bfd_xcoff_ldhdrsz (abfd) + ldhdr->l_nsyms * bfd_xcoff_ldsymsz (abfd);
36593d8817e4Smiod }
36603d8817e4Smiod 
36613d8817e4Smiod static bfd_boolean
xcoff_generate_rtinit(abfd,init,fini,rtld)36623d8817e4Smiod xcoff_generate_rtinit  (abfd, init, fini, rtld)
36633d8817e4Smiod      bfd *abfd;
36643d8817e4Smiod      const char *init;
36653d8817e4Smiod      const char *fini;
36663d8817e4Smiod      bfd_boolean rtld;
36673d8817e4Smiod {
36683d8817e4Smiod   bfd_byte filehdr_ext[FILHSZ];
36693d8817e4Smiod   bfd_byte scnhdr_ext[SCNHSZ];
36703d8817e4Smiod   bfd_byte syment_ext[SYMESZ * 10];
36713d8817e4Smiod   bfd_byte reloc_ext[RELSZ * 3];
36723d8817e4Smiod   bfd_byte *data_buffer;
36733d8817e4Smiod   bfd_size_type data_buffer_size;
36743d8817e4Smiod   bfd_byte *string_table = NULL, *st_tmp = NULL;
36753d8817e4Smiod   bfd_size_type string_table_size;
36763d8817e4Smiod   bfd_vma val;
36773d8817e4Smiod   size_t initsz, finisz;
36783d8817e4Smiod   struct internal_filehdr filehdr;
36793d8817e4Smiod   struct internal_scnhdr scnhdr;
36803d8817e4Smiod   struct internal_syment syment;
36813d8817e4Smiod   union internal_auxent auxent;
36823d8817e4Smiod   struct internal_reloc reloc;
36833d8817e4Smiod 
36843d8817e4Smiod   char *data_name = ".data";
36853d8817e4Smiod   char *rtinit_name = "__rtinit";
36863d8817e4Smiod   char *rtld_name = "__rtld";
36873d8817e4Smiod 
36883d8817e4Smiod   if (! bfd_xcoff_rtinit_size (abfd))
36893d8817e4Smiod     return FALSE;
36903d8817e4Smiod 
36913d8817e4Smiod   initsz = (init == NULL ? 0 : 1 + strlen (init));
36923d8817e4Smiod   finisz = (fini == NULL ? 0 : 1 + strlen (fini));
36933d8817e4Smiod 
36943d8817e4Smiod   /* file header */
36953d8817e4Smiod   memset (filehdr_ext, 0, FILHSZ);
36963d8817e4Smiod   memset (&filehdr, 0, sizeof (struct internal_filehdr));
36973d8817e4Smiod   filehdr.f_magic = bfd_xcoff_magic_number (abfd);
36983d8817e4Smiod   filehdr.f_nscns = 1;
36993d8817e4Smiod   filehdr.f_timdat = 0;
37003d8817e4Smiod   filehdr.f_nsyms = 0;  /* at least 6, no more than 10 */
37013d8817e4Smiod   filehdr.f_symptr = 0; /* set below */
37023d8817e4Smiod   filehdr.f_opthdr = 0;
37033d8817e4Smiod   filehdr.f_flags = 0;
37043d8817e4Smiod 
37053d8817e4Smiod   /* section header */
37063d8817e4Smiod   memset (scnhdr_ext, 0, SCNHSZ);
37073d8817e4Smiod   memset (&scnhdr, 0, sizeof (struct internal_scnhdr));
37083d8817e4Smiod   memcpy (scnhdr.s_name, data_name, strlen (data_name));
37093d8817e4Smiod   scnhdr.s_paddr = 0;
37103d8817e4Smiod   scnhdr.s_vaddr = 0;
37113d8817e4Smiod   scnhdr.s_size = 0;    /* set below */
37123d8817e4Smiod   scnhdr.s_scnptr = FILHSZ + SCNHSZ;
37133d8817e4Smiod   scnhdr.s_relptr = 0;  /* set below */
37143d8817e4Smiod   scnhdr.s_lnnoptr = 0;
37153d8817e4Smiod   scnhdr.s_nreloc = 0;  /* either 1 or 2 */
37163d8817e4Smiod   scnhdr.s_nlnno = 0;
37173d8817e4Smiod   scnhdr.s_flags = STYP_DATA;
37183d8817e4Smiod 
37193d8817e4Smiod   /* .data
37203d8817e4Smiod      0x0000	      0x00000000 : rtl
37213d8817e4Smiod      0x0004	      0x00000010 : offset to init, or 0
37223d8817e4Smiod      0x0008	      0x00000028 : offset to fini, or 0
37233d8817e4Smiod      0x000C	      0x0000000C : size of descriptor
37243d8817e4Smiod      0x0010	      0x00000000 : init, needs a reloc
37253d8817e4Smiod      0x0014	      0x00000040 : offset to init name
37263d8817e4Smiod      0x0018	      0x00000000 : flags, padded to a word
37273d8817e4Smiod      0x001C	      0x00000000 : empty init
37283d8817e4Smiod      0x0020	      0x00000000 :
37293d8817e4Smiod      0x0024	      0x00000000 :
37303d8817e4Smiod      0x0028	      0x00000000 : fini, needs a reloc
37313d8817e4Smiod      0x002C	      0x00000??? : offset to fini name
37323d8817e4Smiod      0x0030	      0x00000000 : flags, padded to a word
37333d8817e4Smiod      0x0034	      0x00000000 : empty fini
37343d8817e4Smiod      0x0038	      0x00000000 :
37353d8817e4Smiod      0x003C	      0x00000000 :
37363d8817e4Smiod      0x0040	      init name
37373d8817e4Smiod      0x0040 + initsz  fini name */
37383d8817e4Smiod 
37393d8817e4Smiod   data_buffer_size = 0x0040 + initsz + finisz;
37403d8817e4Smiod   data_buffer_size = (data_buffer_size + 7) &~ (bfd_size_type) 7;
37413d8817e4Smiod   data_buffer = NULL;
37423d8817e4Smiod   data_buffer = (bfd_byte *) bfd_zmalloc (data_buffer_size);
37433d8817e4Smiod   if (data_buffer == NULL)
37443d8817e4Smiod     return FALSE;
37453d8817e4Smiod 
37463d8817e4Smiod   if (initsz)
37473d8817e4Smiod     {
37483d8817e4Smiod       val = 0x10;
37493d8817e4Smiod       bfd_h_put_32 (abfd, val, &data_buffer[0x04]);
37503d8817e4Smiod       val = 0x40;
37513d8817e4Smiod       bfd_h_put_32 (abfd, val, &data_buffer[0x14]);
37523d8817e4Smiod       memcpy (&data_buffer[val], init, initsz);
37533d8817e4Smiod     }
37543d8817e4Smiod 
37553d8817e4Smiod   if (finisz)
37563d8817e4Smiod     {
37573d8817e4Smiod       val = 0x28;
37583d8817e4Smiod       bfd_h_put_32 (abfd, val, &data_buffer[0x08]);
37593d8817e4Smiod       val = 0x40 + initsz;
37603d8817e4Smiod       bfd_h_put_32 (abfd, val, &data_buffer[0x2C]);
37613d8817e4Smiod       memcpy (&data_buffer[val], fini, finisz);
37623d8817e4Smiod     }
37633d8817e4Smiod 
37643d8817e4Smiod   val = 0x0C;
37653d8817e4Smiod   bfd_h_put_32 (abfd, val, &data_buffer[0x0C]);
37663d8817e4Smiod 
37673d8817e4Smiod   scnhdr.s_size = data_buffer_size;
37683d8817e4Smiod 
37693d8817e4Smiod   /* string table */
37703d8817e4Smiod   string_table_size = 0;
37713d8817e4Smiod   if (initsz > 9)
37723d8817e4Smiod     string_table_size += initsz;
37733d8817e4Smiod   if (finisz > 9)
37743d8817e4Smiod     string_table_size += finisz;
37753d8817e4Smiod   if (string_table_size)
37763d8817e4Smiod     {
37773d8817e4Smiod       string_table_size += 4;
37783d8817e4Smiod       string_table = (bfd_byte *) bfd_zmalloc (string_table_size);
37793d8817e4Smiod       if (string_table == NULL)
37803d8817e4Smiod 	return FALSE;
37813d8817e4Smiod 
37823d8817e4Smiod       val = string_table_size;
37833d8817e4Smiod       bfd_h_put_32 (abfd, val, &string_table[0]);
37843d8817e4Smiod       st_tmp = string_table + 4;
37853d8817e4Smiod     }
37863d8817e4Smiod 
37873d8817e4Smiod   /* symbols
37883d8817e4Smiod      0. .data csect
37893d8817e4Smiod      2. __rtinit
37903d8817e4Smiod      4. init function
37913d8817e4Smiod      6. fini function
37923d8817e4Smiod      8. __rtld  */
37933d8817e4Smiod   memset (syment_ext, 0, 10 * SYMESZ);
37943d8817e4Smiod   memset (reloc_ext, 0, 3 * RELSZ);
37953d8817e4Smiod 
37963d8817e4Smiod   /* .data csect */
37973d8817e4Smiod   memset (&syment, 0, sizeof (struct internal_syment));
37983d8817e4Smiod   memset (&auxent, 0, sizeof (union internal_auxent));
37993d8817e4Smiod   memcpy (syment._n._n_name, data_name, strlen (data_name));
38003d8817e4Smiod   syment.n_scnum = 1;
38013d8817e4Smiod   syment.n_sclass = C_HIDEXT;
38023d8817e4Smiod   syment.n_numaux = 1;
38033d8817e4Smiod   auxent.x_csect.x_scnlen.l = data_buffer_size;
38043d8817e4Smiod   auxent.x_csect.x_smtyp = 3 << 3 | XTY_SD;
38053d8817e4Smiod   auxent.x_csect.x_smclas = XMC_RW;
38063d8817e4Smiod   bfd_coff_swap_sym_out (abfd, &syment,
38073d8817e4Smiod 			 &syment_ext[filehdr.f_nsyms * SYMESZ]);
38083d8817e4Smiod   bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
38093d8817e4Smiod 			 syment.n_numaux,
38103d8817e4Smiod 			 &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
38113d8817e4Smiod   filehdr.f_nsyms += 2;
38123d8817e4Smiod 
38133d8817e4Smiod   /* __rtinit */
38143d8817e4Smiod   memset (&syment, 0, sizeof (struct internal_syment));
38153d8817e4Smiod   memset (&auxent, 0, sizeof (union internal_auxent));
38163d8817e4Smiod   memcpy (syment._n._n_name, rtinit_name, strlen (rtinit_name));
38173d8817e4Smiod   syment.n_scnum = 1;
38183d8817e4Smiod   syment.n_sclass = C_EXT;
38193d8817e4Smiod   syment.n_numaux = 1;
38203d8817e4Smiod   auxent.x_csect.x_smtyp = XTY_LD;
38213d8817e4Smiod   auxent.x_csect.x_smclas = XMC_RW;
38223d8817e4Smiod   bfd_coff_swap_sym_out (abfd, &syment,
38233d8817e4Smiod 			 &syment_ext[filehdr.f_nsyms * SYMESZ]);
38243d8817e4Smiod   bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
38253d8817e4Smiod 			 syment.n_numaux,
38263d8817e4Smiod 			 &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
38273d8817e4Smiod   filehdr.f_nsyms += 2;
38283d8817e4Smiod 
38293d8817e4Smiod   /* init */
38303d8817e4Smiod   if (initsz)
38313d8817e4Smiod     {
38323d8817e4Smiod       memset (&syment, 0, sizeof (struct internal_syment));
38333d8817e4Smiod       memset (&auxent, 0, sizeof (union internal_auxent));
38343d8817e4Smiod 
38353d8817e4Smiod       if (initsz > 9)
38363d8817e4Smiod 	{
38373d8817e4Smiod 	  syment._n._n_n._n_offset = st_tmp - string_table;
38383d8817e4Smiod 	  memcpy (st_tmp, init, initsz);
38393d8817e4Smiod 	  st_tmp += initsz;
38403d8817e4Smiod 	}
38413d8817e4Smiod       else
38423d8817e4Smiod 	memcpy (syment._n._n_name, init, initsz - 1);
38433d8817e4Smiod 
38443d8817e4Smiod       syment.n_sclass = C_EXT;
38453d8817e4Smiod       syment.n_numaux = 1;
38463d8817e4Smiod       bfd_coff_swap_sym_out (abfd, &syment,
38473d8817e4Smiod 			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
38483d8817e4Smiod       bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
38493d8817e4Smiod 			     syment.n_numaux,
38503d8817e4Smiod 			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
38513d8817e4Smiod 
38523d8817e4Smiod       /* reloc */
38533d8817e4Smiod       memset (&reloc, 0, sizeof (struct internal_reloc));
38543d8817e4Smiod       reloc.r_vaddr = 0x0010;
38553d8817e4Smiod       reloc.r_symndx = filehdr.f_nsyms;
38563d8817e4Smiod       reloc.r_type = R_POS;
38573d8817e4Smiod       reloc.r_size = 31;
38583d8817e4Smiod       bfd_coff_swap_reloc_out (abfd, &reloc, &reloc_ext[0]);
38593d8817e4Smiod 
38603d8817e4Smiod       filehdr.f_nsyms += 2;
38613d8817e4Smiod       scnhdr.s_nreloc += 1;
38623d8817e4Smiod     }
38633d8817e4Smiod 
38643d8817e4Smiod   /* fini */
38653d8817e4Smiod   if (finisz)
38663d8817e4Smiod     {
38673d8817e4Smiod       memset (&syment, 0, sizeof (struct internal_syment));
38683d8817e4Smiod       memset (&auxent, 0, sizeof (union internal_auxent));
38693d8817e4Smiod 
38703d8817e4Smiod       if (finisz > 9)
38713d8817e4Smiod 	{
38723d8817e4Smiod 	  syment._n._n_n._n_offset = st_tmp - string_table;
38733d8817e4Smiod 	  memcpy (st_tmp, fini, finisz);
38743d8817e4Smiod 	  st_tmp += finisz;
38753d8817e4Smiod 	}
38763d8817e4Smiod       else
38773d8817e4Smiod 	memcpy (syment._n._n_name, fini, finisz - 1);
38783d8817e4Smiod 
38793d8817e4Smiod       syment.n_sclass = C_EXT;
38803d8817e4Smiod       syment.n_numaux = 1;
38813d8817e4Smiod       bfd_coff_swap_sym_out (abfd, &syment,
38823d8817e4Smiod 			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
38833d8817e4Smiod       bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
38843d8817e4Smiod 			     syment.n_numaux,
38853d8817e4Smiod 			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
38863d8817e4Smiod 
38873d8817e4Smiod       /* reloc */
38883d8817e4Smiod       memset (&reloc, 0, sizeof (struct internal_reloc));
38893d8817e4Smiod       reloc.r_vaddr = 0x0028;
38903d8817e4Smiod       reloc.r_symndx = filehdr.f_nsyms;
38913d8817e4Smiod       reloc.r_type = R_POS;
38923d8817e4Smiod       reloc.r_size = 31;
38933d8817e4Smiod       bfd_coff_swap_reloc_out (abfd, &reloc,
38943d8817e4Smiod 			       &reloc_ext[scnhdr.s_nreloc * RELSZ]);
38953d8817e4Smiod 
38963d8817e4Smiod       filehdr.f_nsyms += 2;
38973d8817e4Smiod       scnhdr.s_nreloc += 1;
38983d8817e4Smiod     }
38993d8817e4Smiod 
39003d8817e4Smiod   if (rtld)
39013d8817e4Smiod     {
39023d8817e4Smiod       memset (&syment, 0, sizeof (struct internal_syment));
39033d8817e4Smiod       memset (&auxent, 0, sizeof (union internal_auxent));
39043d8817e4Smiod       memcpy (syment._n._n_name, rtld_name, strlen (rtld_name));
39053d8817e4Smiod       syment.n_sclass = C_EXT;
39063d8817e4Smiod       syment.n_numaux = 1;
39073d8817e4Smiod       bfd_coff_swap_sym_out (abfd, &syment,
39083d8817e4Smiod 			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
39093d8817e4Smiod       bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
39103d8817e4Smiod 			     syment.n_numaux,
39113d8817e4Smiod 			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
39123d8817e4Smiod 
39133d8817e4Smiod       /* reloc */
39143d8817e4Smiod       memset (&reloc, 0, sizeof (struct internal_reloc));
39153d8817e4Smiod       reloc.r_vaddr = 0x0000;
39163d8817e4Smiod       reloc.r_symndx = filehdr.f_nsyms;
39173d8817e4Smiod       reloc.r_type = R_POS;
39183d8817e4Smiod       reloc.r_size = 31;
39193d8817e4Smiod       bfd_coff_swap_reloc_out (abfd, &reloc,
39203d8817e4Smiod 			       &reloc_ext[scnhdr.s_nreloc * RELSZ]);
39213d8817e4Smiod 
39223d8817e4Smiod       filehdr.f_nsyms += 2;
39233d8817e4Smiod       scnhdr.s_nreloc += 1;
39243d8817e4Smiod     }
39253d8817e4Smiod 
39263d8817e4Smiod   scnhdr.s_relptr = scnhdr.s_scnptr + data_buffer_size;
39273d8817e4Smiod   filehdr.f_symptr = scnhdr.s_relptr + scnhdr.s_nreloc * RELSZ;
39283d8817e4Smiod 
39293d8817e4Smiod   bfd_coff_swap_filehdr_out (abfd, &filehdr, filehdr_ext);
39303d8817e4Smiod   bfd_bwrite (filehdr_ext, FILHSZ, abfd);
39313d8817e4Smiod   bfd_coff_swap_scnhdr_out (abfd, &scnhdr, scnhdr_ext);
39323d8817e4Smiod   bfd_bwrite (scnhdr_ext, SCNHSZ, abfd);
39333d8817e4Smiod   bfd_bwrite (data_buffer, data_buffer_size, abfd);
39343d8817e4Smiod   bfd_bwrite (reloc_ext, scnhdr.s_nreloc * RELSZ, abfd);
39353d8817e4Smiod   bfd_bwrite (syment_ext, filehdr.f_nsyms * SYMESZ, abfd);
39363d8817e4Smiod   bfd_bwrite (string_table, string_table_size, abfd);
39373d8817e4Smiod 
39383d8817e4Smiod   free (data_buffer);
39393d8817e4Smiod   data_buffer = NULL;
39403d8817e4Smiod 
39413d8817e4Smiod   return TRUE;
39423d8817e4Smiod }
39433d8817e4Smiod 
39443d8817e4Smiod 
39453d8817e4Smiod static reloc_howto_type xcoff_dynamic_reloc =
39463d8817e4Smiod HOWTO (0,			/* type */
39473d8817e4Smiod        0,			/* rightshift */
39483d8817e4Smiod        2,			/* size (0 = byte, 1 = short, 2 = long) */
39493d8817e4Smiod        32,			/* bitsize */
39503d8817e4Smiod        FALSE,			/* pc_relative */
39513d8817e4Smiod        0,			/* bitpos */
39523d8817e4Smiod        complain_overflow_bitfield, /* complain_on_overflow */
39533d8817e4Smiod        0,			/* special_function */
39543d8817e4Smiod        "R_POS",			/* name */
39553d8817e4Smiod        TRUE,			/* partial_inplace */
39563d8817e4Smiod        0xffffffff,		/* src_mask */
39573d8817e4Smiod        0xffffffff,		/* dst_mask */
39583d8817e4Smiod        FALSE);			/* pcrel_offset */
39593d8817e4Smiod 
39603d8817e4Smiod /*  glink
39613d8817e4Smiod 
39623d8817e4Smiod    The first word of global linkage code must be modified by filling in
39633d8817e4Smiod    the correct TOC offset.  */
39643d8817e4Smiod 
39653d8817e4Smiod static unsigned long xcoff_glink_code[9] =
39663d8817e4Smiod   {
39673d8817e4Smiod     0x81820000,	/* lwz r12,0(r2) */
39683d8817e4Smiod     0x90410014,	/* stw r2,20(r1) */
39693d8817e4Smiod     0x800c0000,	/* lwz r0,0(r12) */
39703d8817e4Smiod     0x804c0004,	/* lwz r2,4(r12) */
39713d8817e4Smiod     0x7c0903a6,	/* mtctr r0 */
39723d8817e4Smiod     0x4e800420,	/* bctr */
39733d8817e4Smiod     0x00000000,	/* start of traceback table */
39743d8817e4Smiod     0x000c8000,	/* traceback table */
39753d8817e4Smiod     0x00000000,	/* traceback table */
39763d8817e4Smiod   };
39773d8817e4Smiod 
39783d8817e4Smiod 
39793d8817e4Smiod static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
39803d8817e4Smiod   {
39813d8817e4Smiod     { /* COFF backend, defined in libcoff.h.  */
39823d8817e4Smiod       _bfd_xcoff_swap_aux_in,
39833d8817e4Smiod       _bfd_xcoff_swap_sym_in,
39843d8817e4Smiod       coff_swap_lineno_in,
39853d8817e4Smiod       _bfd_xcoff_swap_aux_out,
39863d8817e4Smiod       _bfd_xcoff_swap_sym_out,
39873d8817e4Smiod       coff_swap_lineno_out,
39883d8817e4Smiod       xcoff_swap_reloc_out,
39893d8817e4Smiod       coff_swap_filehdr_out,
39903d8817e4Smiod       coff_swap_aouthdr_out,
39913d8817e4Smiod       coff_swap_scnhdr_out,
39923d8817e4Smiod       FILHSZ,
39933d8817e4Smiod       AOUTSZ,
39943d8817e4Smiod       SCNHSZ,
39953d8817e4Smiod       SYMESZ,
39963d8817e4Smiod       AUXESZ,
39973d8817e4Smiod       RELSZ,
39983d8817e4Smiod       LINESZ,
39993d8817e4Smiod       FILNMLEN,
40003d8817e4Smiod       TRUE,			/* _bfd_coff_long_filenames */
40013d8817e4Smiod       FALSE,			/* _bfd_coff_long_section_names */
40023d8817e4Smiod       3,			/* _bfd_coff_default_section_alignment_power */
40033d8817e4Smiod       FALSE,			/* _bfd_coff_force_symnames_in_strings */
40043d8817e4Smiod       2,			/* _bfd_coff_debug_string_prefix_length */
40053d8817e4Smiod       coff_swap_filehdr_in,
40063d8817e4Smiod       coff_swap_aouthdr_in,
40073d8817e4Smiod       coff_swap_scnhdr_in,
40083d8817e4Smiod       xcoff_swap_reloc_in,
40093d8817e4Smiod       coff_bad_format_hook,
40103d8817e4Smiod       coff_set_arch_mach_hook,
40113d8817e4Smiod       coff_mkobject_hook,
40123d8817e4Smiod       styp_to_sec_flags,
40133d8817e4Smiod       coff_set_alignment_hook,
40143d8817e4Smiod       coff_slurp_symbol_table,
40153d8817e4Smiod       symname_in_debug_hook,
40163d8817e4Smiod       coff_pointerize_aux_hook,
40173d8817e4Smiod       coff_print_aux,
40183d8817e4Smiod       dummy_reloc16_extra_cases,
40193d8817e4Smiod       dummy_reloc16_estimate,
40203d8817e4Smiod       NULL,			/* bfd_coff_sym_is_global */
40213d8817e4Smiod       coff_compute_section_file_positions,
40223d8817e4Smiod       NULL,			/* _bfd_coff_start_final_link */
40233d8817e4Smiod       xcoff_ppc_relocate_section,
40243d8817e4Smiod       coff_rtype_to_howto,
40253d8817e4Smiod       NULL,			/* _bfd_coff_adjust_symndx */
40263d8817e4Smiod       _bfd_generic_link_add_one_symbol,
40273d8817e4Smiod       coff_link_output_has_begun,
40283d8817e4Smiod       coff_final_link_postscript
40293d8817e4Smiod     },
40303d8817e4Smiod 
40313d8817e4Smiod     0x01DF,			/* magic number */
40323d8817e4Smiod     bfd_arch_rs6000,
40333d8817e4Smiod     bfd_mach_rs6k,
40343d8817e4Smiod 
40353d8817e4Smiod     /* Function pointers to xcoff specific swap routines.  */
40363d8817e4Smiod     xcoff_swap_ldhdr_in,
40373d8817e4Smiod     xcoff_swap_ldhdr_out,
40383d8817e4Smiod     xcoff_swap_ldsym_in,
40393d8817e4Smiod     xcoff_swap_ldsym_out,
40403d8817e4Smiod     xcoff_swap_ldrel_in,
40413d8817e4Smiod     xcoff_swap_ldrel_out,
40423d8817e4Smiod 
40433d8817e4Smiod     /* Sizes.  */
40443d8817e4Smiod     LDHDRSZ,
40453d8817e4Smiod     LDSYMSZ,
40463d8817e4Smiod     LDRELSZ,
40473d8817e4Smiod     12,				/* _xcoff_function_descriptor_size */
40483d8817e4Smiod     SMALL_AOUTSZ,
40493d8817e4Smiod 
40503d8817e4Smiod     /* Versions.  */
40513d8817e4Smiod     1,				/* _xcoff_ldhdr_version */
40523d8817e4Smiod 
40533d8817e4Smiod     _bfd_xcoff_put_symbol_name,
40543d8817e4Smiod     _bfd_xcoff_put_ldsymbol_name,
40553d8817e4Smiod     &xcoff_dynamic_reloc,
40563d8817e4Smiod     xcoff_create_csect_from_smclas,
40573d8817e4Smiod 
40583d8817e4Smiod     /* Lineno and reloc count overflow.  */
40593d8817e4Smiod     xcoff_is_lineno_count_overflow,
40603d8817e4Smiod     xcoff_is_reloc_count_overflow,
40613d8817e4Smiod 
40623d8817e4Smiod     xcoff_loader_symbol_offset,
40633d8817e4Smiod     xcoff_loader_reloc_offset,
40643d8817e4Smiod 
40653d8817e4Smiod     /* glink.  */
40663d8817e4Smiod     &xcoff_glink_code[0],
40673d8817e4Smiod     36,				/* _xcoff_glink_size */
40683d8817e4Smiod 
40693d8817e4Smiod     /* rtinit */
40703d8817e4Smiod     64,				/* _xcoff_rtinit_size */
40713d8817e4Smiod     xcoff_generate_rtinit,
40723d8817e4Smiod   };
40733d8817e4Smiod 
40743d8817e4Smiod /* The transfer vector that leads the outside world to all of the above.  */
40753d8817e4Smiod const bfd_target rs6000coff_vec =
40763d8817e4Smiod   {
40773d8817e4Smiod     "aixcoff-rs6000",
40783d8817e4Smiod     bfd_target_xcoff_flavour,
40793d8817e4Smiod     BFD_ENDIAN_BIG,		/* data byte order is big */
40803d8817e4Smiod     BFD_ENDIAN_BIG,		/* header byte order is big */
40813d8817e4Smiod 
40823d8817e4Smiod     (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC
40833d8817e4Smiod      | HAS_SYMS | HAS_LOCALS | WP_TEXT),
40843d8817e4Smiod 
40853d8817e4Smiod     SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA,
40863d8817e4Smiod     0,				/* leading char */
40873d8817e4Smiod     '/',			/* ar_pad_char */
40883d8817e4Smiod     15,				/* ar_max_namelen */
40893d8817e4Smiod 
40903d8817e4Smiod     /* data */
40913d8817e4Smiod     bfd_getb64,
40923d8817e4Smiod     bfd_getb_signed_64,
40933d8817e4Smiod     bfd_putb64,
40943d8817e4Smiod     bfd_getb32,
40953d8817e4Smiod     bfd_getb_signed_32,
40963d8817e4Smiod     bfd_putb32,
40973d8817e4Smiod     bfd_getb16,
40983d8817e4Smiod     bfd_getb_signed_16,
40993d8817e4Smiod     bfd_putb16,
41003d8817e4Smiod 
41013d8817e4Smiod     /* hdrs */
41023d8817e4Smiod     bfd_getb64,
41033d8817e4Smiod     bfd_getb_signed_64,
41043d8817e4Smiod     bfd_putb64,
41053d8817e4Smiod     bfd_getb32,
41063d8817e4Smiod     bfd_getb_signed_32,
41073d8817e4Smiod     bfd_putb32,
41083d8817e4Smiod     bfd_getb16,
41093d8817e4Smiod     bfd_getb_signed_16,
41103d8817e4Smiod     bfd_putb16,
41113d8817e4Smiod 
41123d8817e4Smiod     { /* bfd_check_format */
41133d8817e4Smiod       _bfd_dummy_target,
41143d8817e4Smiod       coff_object_p,
41153d8817e4Smiod       _bfd_xcoff_archive_p,
41163d8817e4Smiod       CORE_FILE_P
41173d8817e4Smiod     },
41183d8817e4Smiod 
41193d8817e4Smiod     { /* bfd_set_format */
41203d8817e4Smiod       bfd_false,
41213d8817e4Smiod       coff_mkobject,
41223d8817e4Smiod       _bfd_generic_mkarchive,
41233d8817e4Smiod       bfd_false
41243d8817e4Smiod     },
41253d8817e4Smiod 
41263d8817e4Smiod     {/* bfd_write_contents */
41273d8817e4Smiod       bfd_false,
41283d8817e4Smiod       coff_write_object_contents,
41293d8817e4Smiod       _bfd_xcoff_write_archive_contents,
41303d8817e4Smiod       bfd_false
41313d8817e4Smiod     },
41323d8817e4Smiod 
41333d8817e4Smiod     /* Generic */
41343d8817e4Smiod     bfd_true,
41353d8817e4Smiod     bfd_true,
41363d8817e4Smiod     coff_new_section_hook,
41373d8817e4Smiod     _bfd_generic_get_section_contents,
41383d8817e4Smiod     _bfd_generic_get_section_contents_in_window,
41393d8817e4Smiod 
41403d8817e4Smiod     /* Copy */
41413d8817e4Smiod     _bfd_xcoff_copy_private_bfd_data,
41423d8817e4Smiod     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
41433d8817e4Smiod     _bfd_generic_init_private_section_data,
41443d8817e4Smiod     ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
41453d8817e4Smiod     ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
41463d8817e4Smiod     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
41473d8817e4Smiod     ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
41483d8817e4Smiod     ((bfd_boolean (*) (bfd *, void * )) bfd_true),
41493d8817e4Smiod 
41503d8817e4Smiod     /* Core */
41513d8817e4Smiod     coff_core_file_failing_command,
41523d8817e4Smiod     coff_core_file_failing_signal,
41533d8817e4Smiod     coff_core_file_matches_executable_p,
41543d8817e4Smiod 
41553d8817e4Smiod     /* Archive */
41563d8817e4Smiod     _bfd_xcoff_slurp_armap,
41573d8817e4Smiod     bfd_false,
41583d8817e4Smiod     ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
41593d8817e4Smiod     bfd_dont_truncate_arname,
41603d8817e4Smiod     _bfd_xcoff_write_armap,
41613d8817e4Smiod     _bfd_xcoff_read_ar_hdr,
41623d8817e4Smiod     _bfd_xcoff_openr_next_archived_file,
41633d8817e4Smiod     _bfd_generic_get_elt_at_index,
41643d8817e4Smiod     _bfd_xcoff_stat_arch_elt,
41653d8817e4Smiod     bfd_true,
41663d8817e4Smiod 
41673d8817e4Smiod     /* Symbols */
41683d8817e4Smiod     coff_get_symtab_upper_bound,
41693d8817e4Smiod     coff_canonicalize_symtab,
41703d8817e4Smiod     coff_make_empty_symbol,
41713d8817e4Smiod     coff_print_symbol,
41723d8817e4Smiod     coff_get_symbol_info,
41733d8817e4Smiod     _bfd_xcoff_is_local_label_name,
41743d8817e4Smiod     coff_bfd_is_target_special_symbol,
41753d8817e4Smiod     coff_get_lineno,
41763d8817e4Smiod     coff_find_nearest_line,
41773d8817e4Smiod     _bfd_generic_find_line,
41783d8817e4Smiod     coff_find_inliner_info,
41793d8817e4Smiod     coff_bfd_make_debug_symbol,
41803d8817e4Smiod     _bfd_generic_read_minisymbols,
41813d8817e4Smiod     _bfd_generic_minisymbol_to_symbol,
41823d8817e4Smiod 
41833d8817e4Smiod     /* Reloc */
41843d8817e4Smiod     coff_get_reloc_upper_bound,
41853d8817e4Smiod     coff_canonicalize_reloc,
41863d8817e4Smiod     _bfd_xcoff_reloc_type_lookup,
41873d8817e4Smiod 
41883d8817e4Smiod     /* Write */
41893d8817e4Smiod     coff_set_arch_mach,
41903d8817e4Smiod     coff_set_section_contents,
41913d8817e4Smiod 
41923d8817e4Smiod     /* Link */
41933d8817e4Smiod     _bfd_xcoff_sizeof_headers,
41943d8817e4Smiod     bfd_generic_get_relocated_section_contents,
41953d8817e4Smiod     bfd_generic_relax_section,
41963d8817e4Smiod     _bfd_xcoff_bfd_link_hash_table_create,
41973d8817e4Smiod     _bfd_generic_link_hash_table_free,
41983d8817e4Smiod     _bfd_xcoff_bfd_link_add_symbols,
41993d8817e4Smiod     _bfd_generic_link_just_syms,
42003d8817e4Smiod     _bfd_xcoff_bfd_final_link,
42013d8817e4Smiod     _bfd_generic_link_split_section,
42023d8817e4Smiod     bfd_generic_gc_sections,
42033d8817e4Smiod     bfd_generic_merge_sections,
42043d8817e4Smiod     bfd_generic_is_group_section,
42053d8817e4Smiod     bfd_generic_discard_group,
42063d8817e4Smiod     _bfd_generic_section_already_linked,
42073d8817e4Smiod 
42083d8817e4Smiod     /* Dynamic */
42093d8817e4Smiod     _bfd_xcoff_get_dynamic_symtab_upper_bound,
42103d8817e4Smiod     _bfd_xcoff_canonicalize_dynamic_symtab,
42113d8817e4Smiod     _bfd_nodynamic_get_synthetic_symtab,
42123d8817e4Smiod     _bfd_xcoff_get_dynamic_reloc_upper_bound,
42133d8817e4Smiod     _bfd_xcoff_canonicalize_dynamic_reloc,
42143d8817e4Smiod 
42153d8817e4Smiod     /* Opposite endian version, none exists */
42163d8817e4Smiod     NULL,
42173d8817e4Smiod 
42183d8817e4Smiod     (void *) &bfd_xcoff_backend_data,
42193d8817e4Smiod   };
42203d8817e4Smiod 
42213d8817e4Smiod /* xcoff-powermac target
42223d8817e4Smiod    Old target.
42233d8817e4Smiod    Only difference between this target and the rs6000 target is the
42243d8817e4Smiod    the default architecture and machine type used in coffcode.h
42253d8817e4Smiod 
42263d8817e4Smiod    PowerPC Macs use the same magic numbers as RS/6000
42273d8817e4Smiod    (because that's how they were bootstrapped originally),
42283d8817e4Smiod    but they are always PowerPC architecture.  */
42293d8817e4Smiod static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
42303d8817e4Smiod   {
42313d8817e4Smiod     { /* COFF backend, defined in libcoff.h.  */
42323d8817e4Smiod       _bfd_xcoff_swap_aux_in,
42333d8817e4Smiod       _bfd_xcoff_swap_sym_in,
42343d8817e4Smiod       coff_swap_lineno_in,
42353d8817e4Smiod       _bfd_xcoff_swap_aux_out,
42363d8817e4Smiod       _bfd_xcoff_swap_sym_out,
42373d8817e4Smiod       coff_swap_lineno_out,
42383d8817e4Smiod       xcoff_swap_reloc_out,
42393d8817e4Smiod       coff_swap_filehdr_out,
42403d8817e4Smiod       coff_swap_aouthdr_out,
42413d8817e4Smiod       coff_swap_scnhdr_out,
42423d8817e4Smiod       FILHSZ,
42433d8817e4Smiod       AOUTSZ,
42443d8817e4Smiod       SCNHSZ,
42453d8817e4Smiod       SYMESZ,
42463d8817e4Smiod       AUXESZ,
42473d8817e4Smiod       RELSZ,
42483d8817e4Smiod       LINESZ,
42493d8817e4Smiod       FILNMLEN,
42503d8817e4Smiod       TRUE,			/* _bfd_coff_long_filenames */
42513d8817e4Smiod       FALSE,			/* _bfd_coff_long_section_names */
42523d8817e4Smiod       3,			/* _bfd_coff_default_section_alignment_power */
42533d8817e4Smiod       FALSE,			/* _bfd_coff_force_symnames_in_strings */
42543d8817e4Smiod       2,			/* _bfd_coff_debug_string_prefix_length */
42553d8817e4Smiod       coff_swap_filehdr_in,
42563d8817e4Smiod       coff_swap_aouthdr_in,
42573d8817e4Smiod       coff_swap_scnhdr_in,
42583d8817e4Smiod       xcoff_swap_reloc_in,
42593d8817e4Smiod       coff_bad_format_hook,
42603d8817e4Smiod       coff_set_arch_mach_hook,
42613d8817e4Smiod       coff_mkobject_hook,
42623d8817e4Smiod       styp_to_sec_flags,
42633d8817e4Smiod       coff_set_alignment_hook,
42643d8817e4Smiod       coff_slurp_symbol_table,
42653d8817e4Smiod       symname_in_debug_hook,
42663d8817e4Smiod       coff_pointerize_aux_hook,
42673d8817e4Smiod       coff_print_aux,
42683d8817e4Smiod       dummy_reloc16_extra_cases,
42693d8817e4Smiod       dummy_reloc16_estimate,
42703d8817e4Smiod       NULL,			/* bfd_coff_sym_is_global */
42713d8817e4Smiod       coff_compute_section_file_positions,
42723d8817e4Smiod       NULL,			/* _bfd_coff_start_final_link */
42733d8817e4Smiod       xcoff_ppc_relocate_section,
42743d8817e4Smiod       coff_rtype_to_howto,
42753d8817e4Smiod       NULL,			/* _bfd_coff_adjust_symndx */
42763d8817e4Smiod       _bfd_generic_link_add_one_symbol,
42773d8817e4Smiod       coff_link_output_has_begun,
42783d8817e4Smiod       coff_final_link_postscript
42793d8817e4Smiod     },
42803d8817e4Smiod 
42813d8817e4Smiod     0x01DF,			/* magic number */
42823d8817e4Smiod     bfd_arch_powerpc,
42833d8817e4Smiod     bfd_mach_ppc,
42843d8817e4Smiod 
42853d8817e4Smiod     /* Function pointers to xcoff specific swap routines.  */
42863d8817e4Smiod     xcoff_swap_ldhdr_in,
42873d8817e4Smiod     xcoff_swap_ldhdr_out,
42883d8817e4Smiod     xcoff_swap_ldsym_in,
42893d8817e4Smiod     xcoff_swap_ldsym_out,
42903d8817e4Smiod     xcoff_swap_ldrel_in,
42913d8817e4Smiod     xcoff_swap_ldrel_out,
42923d8817e4Smiod 
42933d8817e4Smiod     /* Sizes.  */
42943d8817e4Smiod     LDHDRSZ,
42953d8817e4Smiod     LDSYMSZ,
42963d8817e4Smiod     LDRELSZ,
42973d8817e4Smiod     12,				/* _xcoff_function_descriptor_size */
42983d8817e4Smiod     SMALL_AOUTSZ,
42993d8817e4Smiod 
43003d8817e4Smiod     /* Versions.  */
43013d8817e4Smiod     1,				/* _xcoff_ldhdr_version */
43023d8817e4Smiod 
43033d8817e4Smiod     _bfd_xcoff_put_symbol_name,
43043d8817e4Smiod     _bfd_xcoff_put_ldsymbol_name,
43053d8817e4Smiod     &xcoff_dynamic_reloc,
43063d8817e4Smiod     xcoff_create_csect_from_smclas,
43073d8817e4Smiod 
43083d8817e4Smiod     /* Lineno and reloc count overflow.  */
43093d8817e4Smiod     xcoff_is_lineno_count_overflow,
43103d8817e4Smiod     xcoff_is_reloc_count_overflow,
43113d8817e4Smiod 
43123d8817e4Smiod     xcoff_loader_symbol_offset,
43133d8817e4Smiod     xcoff_loader_reloc_offset,
43143d8817e4Smiod 
43153d8817e4Smiod     /* glink.  */
43163d8817e4Smiod     &xcoff_glink_code[0],
43173d8817e4Smiod     36,				/* _xcoff_glink_size */
43183d8817e4Smiod 
43193d8817e4Smiod     /* rtinit */
43203d8817e4Smiod     0,				/* _xcoff_rtinit_size */
43213d8817e4Smiod     xcoff_generate_rtinit,
43223d8817e4Smiod   };
43233d8817e4Smiod 
43243d8817e4Smiod /* The transfer vector that leads the outside world to all of the above.  */
43253d8817e4Smiod const bfd_target pmac_xcoff_vec =
43263d8817e4Smiod   {
43273d8817e4Smiod     "xcoff-powermac",
43283d8817e4Smiod     bfd_target_xcoff_flavour,
43293d8817e4Smiod     BFD_ENDIAN_BIG,		/* data byte order is big */
43303d8817e4Smiod     BFD_ENDIAN_BIG,		/* header byte order is big */
43313d8817e4Smiod 
43323d8817e4Smiod     (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC
43333d8817e4Smiod      | HAS_SYMS | HAS_LOCALS | WP_TEXT),
43343d8817e4Smiod 
43353d8817e4Smiod     SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA,
43363d8817e4Smiod     0,				/* leading char */
43373d8817e4Smiod     '/',			/* ar_pad_char */
43383d8817e4Smiod     15,				/* ar_max_namelen */
43393d8817e4Smiod 
43403d8817e4Smiod     /* data */
43413d8817e4Smiod     bfd_getb64,
43423d8817e4Smiod     bfd_getb_signed_64,
43433d8817e4Smiod     bfd_putb64,
43443d8817e4Smiod     bfd_getb32,
43453d8817e4Smiod     bfd_getb_signed_32,
43463d8817e4Smiod     bfd_putb32,
43473d8817e4Smiod     bfd_getb16,
43483d8817e4Smiod     bfd_getb_signed_16,
43493d8817e4Smiod     bfd_putb16,
43503d8817e4Smiod 
43513d8817e4Smiod     /* hdrs */
43523d8817e4Smiod     bfd_getb64,
43533d8817e4Smiod     bfd_getb_signed_64,
43543d8817e4Smiod     bfd_putb64,
43553d8817e4Smiod     bfd_getb32,
43563d8817e4Smiod     bfd_getb_signed_32,
43573d8817e4Smiod     bfd_putb32,
43583d8817e4Smiod     bfd_getb16,
43593d8817e4Smiod     bfd_getb_signed_16,
43603d8817e4Smiod     bfd_putb16,
43613d8817e4Smiod 
43623d8817e4Smiod     { /* bfd_check_format */
43633d8817e4Smiod       _bfd_dummy_target,
43643d8817e4Smiod       coff_object_p,
43653d8817e4Smiod       _bfd_xcoff_archive_p,
43663d8817e4Smiod       CORE_FILE_P
43673d8817e4Smiod     },
43683d8817e4Smiod 
43693d8817e4Smiod     { /* bfd_set_format */
43703d8817e4Smiod       bfd_false,
43713d8817e4Smiod       coff_mkobject,
43723d8817e4Smiod       _bfd_generic_mkarchive,
43733d8817e4Smiod       bfd_false
43743d8817e4Smiod     },
43753d8817e4Smiod 
43763d8817e4Smiod     {/* bfd_write_contents */
43773d8817e4Smiod       bfd_false,
43783d8817e4Smiod       coff_write_object_contents,
43793d8817e4Smiod       _bfd_xcoff_write_archive_contents,
43803d8817e4Smiod       bfd_false
43813d8817e4Smiod     },
43823d8817e4Smiod 
43833d8817e4Smiod     /* Generic */
43843d8817e4Smiod     bfd_true,
43853d8817e4Smiod     bfd_true,
43863d8817e4Smiod     coff_new_section_hook,
43873d8817e4Smiod     _bfd_generic_get_section_contents,
43883d8817e4Smiod     _bfd_generic_get_section_contents_in_window,
43893d8817e4Smiod 
43903d8817e4Smiod     /* Copy */
43913d8817e4Smiod     _bfd_xcoff_copy_private_bfd_data,
43923d8817e4Smiod     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
43933d8817e4Smiod     _bfd_generic_init_private_section_data,
43943d8817e4Smiod     ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
43953d8817e4Smiod     ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
43963d8817e4Smiod     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
43973d8817e4Smiod     ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
43983d8817e4Smiod     ((bfd_boolean (*) (bfd *, void * )) bfd_true),
43993d8817e4Smiod 
44003d8817e4Smiod     /* Core */
44013d8817e4Smiod     coff_core_file_failing_command,
44023d8817e4Smiod     coff_core_file_failing_signal,
44033d8817e4Smiod     coff_core_file_matches_executable_p,
44043d8817e4Smiod 
44053d8817e4Smiod     /* Archive */
44063d8817e4Smiod     _bfd_xcoff_slurp_armap,
44073d8817e4Smiod     bfd_false,
44083d8817e4Smiod     ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
44093d8817e4Smiod     bfd_dont_truncate_arname,
44103d8817e4Smiod     _bfd_xcoff_write_armap,
44113d8817e4Smiod     _bfd_xcoff_read_ar_hdr,
44123d8817e4Smiod     _bfd_xcoff_openr_next_archived_file,
44133d8817e4Smiod     _bfd_generic_get_elt_at_index,
44143d8817e4Smiod     _bfd_xcoff_stat_arch_elt,
44153d8817e4Smiod     bfd_true,
44163d8817e4Smiod 
44173d8817e4Smiod     /* Symbols */
44183d8817e4Smiod     coff_get_symtab_upper_bound,
44193d8817e4Smiod     coff_canonicalize_symtab,
44203d8817e4Smiod     coff_make_empty_symbol,
44213d8817e4Smiod     coff_print_symbol,
44223d8817e4Smiod     coff_get_symbol_info,
44233d8817e4Smiod     _bfd_xcoff_is_local_label_name,
44243d8817e4Smiod     coff_bfd_is_target_special_symbol,
44253d8817e4Smiod     coff_get_lineno,
44263d8817e4Smiod     coff_find_nearest_line,
44273d8817e4Smiod     _bfd_generic_find_line,
44283d8817e4Smiod     coff_find_inliner_info,
44293d8817e4Smiod     coff_bfd_make_debug_symbol,
44303d8817e4Smiod     _bfd_generic_read_minisymbols,
44313d8817e4Smiod     _bfd_generic_minisymbol_to_symbol,
44323d8817e4Smiod 
44333d8817e4Smiod     /* Reloc */
44343d8817e4Smiod     coff_get_reloc_upper_bound,
44353d8817e4Smiod     coff_canonicalize_reloc,
44363d8817e4Smiod     _bfd_xcoff_reloc_type_lookup,
44373d8817e4Smiod 
44383d8817e4Smiod     /* Write */
44393d8817e4Smiod     coff_set_arch_mach,
44403d8817e4Smiod     coff_set_section_contents,
44413d8817e4Smiod 
44423d8817e4Smiod     /* Link */
44433d8817e4Smiod     _bfd_xcoff_sizeof_headers,
44443d8817e4Smiod     bfd_generic_get_relocated_section_contents,
44453d8817e4Smiod     bfd_generic_relax_section,
44463d8817e4Smiod     _bfd_xcoff_bfd_link_hash_table_create,
44473d8817e4Smiod     _bfd_generic_link_hash_table_free,
44483d8817e4Smiod     _bfd_xcoff_bfd_link_add_symbols,
44493d8817e4Smiod     _bfd_generic_link_just_syms,
44503d8817e4Smiod     _bfd_xcoff_bfd_final_link,
44513d8817e4Smiod     _bfd_generic_link_split_section,
44523d8817e4Smiod     bfd_generic_gc_sections,
44533d8817e4Smiod     bfd_generic_merge_sections,
44543d8817e4Smiod     bfd_generic_is_group_section,
44553d8817e4Smiod     bfd_generic_discard_group,
44563d8817e4Smiod     _bfd_generic_section_already_linked,
44573d8817e4Smiod 
44583d8817e4Smiod     /* Dynamic */
44593d8817e4Smiod     _bfd_xcoff_get_dynamic_symtab_upper_bound,
44603d8817e4Smiod     _bfd_xcoff_canonicalize_dynamic_symtab,
44613d8817e4Smiod     _bfd_nodynamic_get_synthetic_symtab,
44623d8817e4Smiod     _bfd_xcoff_get_dynamic_reloc_upper_bound,
44633d8817e4Smiod     _bfd_xcoff_canonicalize_dynamic_reloc,
44643d8817e4Smiod 
44653d8817e4Smiod     /* Opposite endian version, none exists */
44663d8817e4Smiod     NULL,
44673d8817e4Smiod 
44683d8817e4Smiod     (void *) &bfd_pmac_xcoff_backend_data,
44693d8817e4Smiod   };
4470