191041Sobrien/* BFD back-end for IBM RS/6000 "XCOFF64" files.
2218822Sdim   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
391041Sobrien   Free Software Foundation, Inc.
491041Sobrien   Written Clinton Popetz.
591041Sobrien   Contributed by Cygnus Support.
691041Sobrien
7104834Sobrien   This file is part of BFD, the Binary File Descriptor library.
891041Sobrien
9104834Sobrien   This program is free software; you can redistribute it and/or modify
10104834Sobrien   it under the terms of the GNU General Public License as published by
11104834Sobrien   the Free Software Foundation; either version 2 of the License, or
12104834Sobrien   (at your option) any later version.
1391041Sobrien
14104834Sobrien   This program is distributed in the hope that it will be useful,
15104834Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
16104834Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17104834Sobrien   GNU General Public License for more details.
1891041Sobrien
19104834Sobrien   You should have received a copy of the GNU General Public License
20104834Sobrien   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2291041Sobrien
23218822Sdim#include "sysdep.h"
2491041Sobrien#include "bfd.h"
2591041Sobrien#include "bfdlink.h"
2691041Sobrien#include "libbfd.h"
2791041Sobrien#include "coff/internal.h"
2891041Sobrien#include "coff/xcoff.h"
2991041Sobrien#include "coff/rs6k64.h"
3091041Sobrien#include "libcoff.h"
3191041Sobrien#include "libxcoff.h"
3291041Sobrien
3391041Sobrien#define GET_FILEHDR_SYMPTR H_GET_64
3491041Sobrien#define PUT_FILEHDR_SYMPTR H_PUT_64
3591041Sobrien#define GET_AOUTHDR_DATA_START H_GET_64
3691041Sobrien#define PUT_AOUTHDR_DATA_START H_PUT_64
3791041Sobrien#define GET_AOUTHDR_TEXT_START H_GET_64
3891041Sobrien#define PUT_AOUTHDR_TEXT_START H_PUT_64
3991041Sobrien#define GET_AOUTHDR_TSIZE H_GET_64
4091041Sobrien#define PUT_AOUTHDR_TSIZE H_PUT_64
4191041Sobrien#define GET_AOUTHDR_DSIZE H_GET_64
4291041Sobrien#define PUT_AOUTHDR_DSIZE H_PUT_64
4391041Sobrien#define GET_AOUTHDR_BSIZE H_GET_64
4491041Sobrien#define PUT_AOUTHDR_BSIZE H_PUT_64
4591041Sobrien#define GET_AOUTHDR_ENTRY H_GET_64
4691041Sobrien#define PUT_AOUTHDR_ENTRY H_PUT_64
4791041Sobrien#define GET_SCNHDR_PADDR H_GET_64
4891041Sobrien#define PUT_SCNHDR_PADDR H_PUT_64
4991041Sobrien#define GET_SCNHDR_VADDR H_GET_64
5091041Sobrien#define PUT_SCNHDR_VADDR H_PUT_64
5191041Sobrien#define GET_SCNHDR_SIZE H_GET_64
5291041Sobrien#define PUT_SCNHDR_SIZE H_PUT_64
5391041Sobrien#define GET_SCNHDR_SCNPTR H_GET_64
5491041Sobrien#define PUT_SCNHDR_SCNPTR H_PUT_64
5591041Sobrien#define GET_SCNHDR_RELPTR H_GET_64
5691041Sobrien#define PUT_SCNHDR_RELPTR H_PUT_64
5791041Sobrien#define GET_SCNHDR_LNNOPTR H_GET_64
5891041Sobrien#define PUT_SCNHDR_LNNOPTR H_PUT_64
5991041Sobrien#define GET_SCNHDR_NRELOC H_GET_32
6091041Sobrien#define MAX_SCNHDR_NRELOC 0xffffffff
6191041Sobrien#define PUT_SCNHDR_NRELOC H_PUT_32
6291041Sobrien#define GET_SCNHDR_NLNNO H_GET_32
6391041Sobrien#define MAX_SCNHDR_NLNNO 0xffffffff
6491041Sobrien#define PUT_SCNHDR_NLNNO H_PUT_32
6591041Sobrien#define GET_RELOC_VADDR H_GET_64
6691041Sobrien#define PUT_RELOC_VADDR H_PUT_64
6791041Sobrien
6891041Sobrien#define COFF_FORCE_SYMBOLS_IN_STRINGS
6991041Sobrien#define COFF_DEBUG_STRING_WIDE_PREFIX
7091041Sobrien
7191041Sobrien
7291041Sobrien#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT)			\
7391041Sobrien  do									\
7491041Sobrien    {									\
7591041Sobrien      memset (((SCNHDR *) EXT)->s_pad, 0,				\
7691041Sobrien	      sizeof (((SCNHDR *) EXT)->s_pad));			\
7791041Sobrien    }									\
7891041Sobrien  while (0)
7991041Sobrien
8091041Sobrien#define NO_COFF_LINENOS
8191041Sobrien
8291041Sobrien#define coff_SWAP_lineno_in _bfd_xcoff64_swap_lineno_in
8391041Sobrien#define coff_SWAP_lineno_out _bfd_xcoff64_swap_lineno_out
8491041Sobrien
85130561Sobrienstatic void _bfd_xcoff64_swap_lineno_in
86130561Sobrien  PARAMS ((bfd *, PTR, PTR));
87130561Sobrienstatic unsigned int _bfd_xcoff64_swap_lineno_out
88130561Sobrien  PARAMS ((bfd *, PTR, PTR));
89130561Sobrienstatic bfd_boolean _bfd_xcoff64_put_symbol_name
90104834Sobrien  PARAMS ((bfd *, struct bfd_strtab_hash *, struct internal_syment *,
91104834Sobrien	   const char *));
92130561Sobrienstatic bfd_boolean _bfd_xcoff64_put_ldsymbol_name
9391041Sobrien  PARAMS ((bfd *, struct xcoff_loader_info *, struct internal_ldsym *,
9491041Sobrien	   const char *));
95130561Sobrienstatic void _bfd_xcoff64_swap_sym_in
96130561Sobrien  PARAMS ((bfd *, PTR, PTR));
97130561Sobrienstatic unsigned int _bfd_xcoff64_swap_sym_out
98130561Sobrien  PARAMS ((bfd *, PTR, PTR));
9991041Sobrienstatic void _bfd_xcoff64_swap_aux_in
10091041Sobrien  PARAMS ((bfd *, PTR, int, int, int, int, PTR));
10191041Sobrienstatic unsigned int _bfd_xcoff64_swap_aux_out
10291041Sobrien  PARAMS ((bfd *, PTR, int, int, int, int, PTR));
103130561Sobrienstatic void xcoff64_swap_reloc_in
104130561Sobrien  PARAMS ((bfd *, PTR, PTR));
105130561Sobrienstatic unsigned int xcoff64_swap_reloc_out
106130561Sobrien  PARAMS ((bfd *, PTR, PTR));
107130561Sobrienextern bfd_boolean _bfd_xcoff_mkobject
108130561Sobrien  PARAMS ((bfd *));
109130561Sobrienextern bfd_boolean _bfd_xcoff_copy_private_bfd_data
110130561Sobrien  PARAMS ((bfd *, bfd *));
111130561Sobrienextern bfd_boolean _bfd_xcoff_is_local_label_name
112130561Sobrien  PARAMS ((bfd *, const char *));
11391041Sobrienextern void xcoff64_rtype2howto
11491041Sobrien  PARAMS ((arelent *, struct internal_reloc *));
11591041Sobrienextern reloc_howto_type * xcoff64_reloc_type_lookup
11691041Sobrien  PARAMS ((bfd *, bfd_reloc_code_real_type));
117130561Sobrienextern bfd_boolean _bfd_xcoff_slurp_armap
118130561Sobrien  PARAMS ((bfd *));
119130561Sobrienextern PTR _bfd_xcoff_read_ar_hdr
120130561Sobrien  PARAMS ((bfd *));
121130561Sobrienextern bfd *_bfd_xcoff_openr_next_archived_file
122130561Sobrien  PARAMS ((bfd *, bfd *));
123130561Sobrienextern int _bfd_xcoff_stat_arch_elt
124130561Sobrien  PARAMS ((bfd *, struct stat *));
125130561Sobrienextern bfd_boolean _bfd_xcoff_write_armap
12691041Sobrien  PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
127130561Sobrienextern bfd_boolean _bfd_xcoff_write_archive_contents
128130561Sobrien  PARAMS ((bfd *));
129130561Sobrienextern int _bfd_xcoff_sizeof_headers
130218822Sdim  PARAMS ((bfd *, struct bfd_link_info *));
131130561Sobrienextern void _bfd_xcoff_swap_sym_in
132130561Sobrien  PARAMS ((bfd *, PTR, PTR));
133130561Sobrienextern unsigned int _bfd_xcoff_swap_sym_out
134130561Sobrien  PARAMS ((bfd *, PTR, PTR));
13591041Sobrienextern void _bfd_xcoff_swap_aux_in
13691041Sobrien  PARAMS ((bfd *, PTR, int, int, int, int, PTR));
13791041Sobrienextern unsigned int _bfd_xcoff_swap_aux_out
13891041Sobrien  PARAMS ((bfd *, PTR, int, int, int, int, PTR));
13991041Sobrienstatic void xcoff64_swap_ldhdr_in
14091041Sobrien  PARAMS ((bfd *, const PTR, struct internal_ldhdr *));
14191041Sobrienstatic void xcoff64_swap_ldhdr_out
14291041Sobrien  PARAMS ((bfd *, const struct internal_ldhdr *, PTR d));
14391041Sobrienstatic void xcoff64_swap_ldsym_in
14491041Sobrien  PARAMS ((bfd *, const PTR, struct internal_ldsym *));
14591041Sobrienstatic void xcoff64_swap_ldsym_out
14691041Sobrien  PARAMS ((bfd *, const struct internal_ldsym *, PTR d));
14791041Sobrienstatic void xcoff64_swap_ldrel_in
14891041Sobrien  PARAMS ((bfd *, const PTR, struct internal_ldrel *));
14991041Sobrienstatic void xcoff64_swap_ldrel_out
15091041Sobrien  PARAMS ((bfd *, const struct internal_ldrel *, PTR d));
151130561Sobrienstatic bfd_boolean xcoff64_write_object_contents
152130561Sobrien  PARAMS ((bfd *));
153130561Sobrienstatic bfd_boolean xcoff64_ppc_relocate_section
15491041Sobrien  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
155104834Sobrien	   struct internal_reloc *, struct internal_syment *,
156104834Sobrien	   asection **));
157130561Sobrienstatic bfd_boolean xcoff64_slurp_armap
158130561Sobrien  PARAMS ((bfd *));
159130561Sobrienstatic const bfd_target *xcoff64_archive_p
160130561Sobrien  PARAMS ((bfd *));
161130561Sobrienstatic bfd *xcoff64_openr_next_archived_file
162130561Sobrien  PARAMS ((bfd *, bfd *));
163130561Sobrienstatic int xcoff64_sizeof_headers
164218822Sdim  PARAMS ((bfd *, struct bfd_link_info *));
16591041Sobrienstatic asection *xcoff64_create_csect_from_smclas
16691041Sobrien  PARAMS ((bfd *, union internal_auxent *, const char *));
167130561Sobrienstatic bfd_boolean xcoff64_is_lineno_count_overflow
168130561Sobrien  PARAMS ((bfd *, bfd_vma));
169130561Sobrienstatic bfd_boolean xcoff64_is_reloc_count_overflow
170130561Sobrien  PARAMS ((bfd *, bfd_vma));
17191041Sobrienstatic bfd_vma xcoff64_loader_symbol_offset
17291041Sobrien  PARAMS ((bfd *, struct internal_ldhdr *));
17391041Sobrienstatic bfd_vma xcoff64_loader_reloc_offset
17491041Sobrien  PARAMS ((bfd *, struct internal_ldhdr *));
175130561Sobrienstatic bfd_boolean xcoff64_generate_rtinit
176130561Sobrien  PARAMS ((bfd *, const char *, const char *, bfd_boolean));
177130561Sobrienstatic bfd_boolean xcoff64_bad_format_hook
178130561Sobrien  PARAMS ((bfd *, PTR ));
17991041Sobrien
180104834Sobrien/* Relocation functions */
181130561Sobrienstatic bfd_boolean xcoff64_reloc_type_br
182130561Sobrien  PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
18391041Sobrien
184130561Sobrienbfd_boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
185104834Sobrien  PARAMS ((XCOFF_RELOC_FUNCTION_ARGS)) =
186104834Sobrien{
187130561Sobrien  xcoff_reloc_type_pos,	 /* R_POS   (0x00) */
188130561Sobrien  xcoff_reloc_type_neg,	 /* R_NEG   (0x01) */
189130561Sobrien  xcoff_reloc_type_rel,	 /* R_REL   (0x02) */
190130561Sobrien  xcoff_reloc_type_toc,	 /* R_TOC   (0x03) */
191104834Sobrien  xcoff_reloc_type_fail, /* R_RTB   (0x04) */
192130561Sobrien  xcoff_reloc_type_toc,	 /* R_GL    (0x05) */
193130561Sobrien  xcoff_reloc_type_toc,	 /* R_TCL   (0x06) */
194130561Sobrien  xcoff_reloc_type_fail, /*	    (0x07) */
195130561Sobrien  xcoff_reloc_type_ba,	 /* R_BA    (0x08) */
196130561Sobrien  xcoff_reloc_type_fail, /*	    (0x09) */
197104834Sobrien  xcoff64_reloc_type_br, /* R_BR    (0x0a) */
198130561Sobrien  xcoff_reloc_type_fail, /*	    (0x0b) */
199130561Sobrien  xcoff_reloc_type_pos,	 /* R_RL    (0x0c) */
200130561Sobrien  xcoff_reloc_type_pos,	 /* R_RLA   (0x0d) */
201130561Sobrien  xcoff_reloc_type_fail, /*	    (0x0e) */
202104834Sobrien  xcoff_reloc_type_noop, /* R_REF   (0x0f) */
203130561Sobrien  xcoff_reloc_type_fail, /*	    (0x10) */
204130561Sobrien  xcoff_reloc_type_fail, /*	    (0x11) */
205130561Sobrien  xcoff_reloc_type_toc,	 /* R_TRL   (0x12) */
206130561Sobrien  xcoff_reloc_type_toc,	 /* R_TRLA  (0x13) */
207104834Sobrien  xcoff_reloc_type_fail, /* R_RRTBI (0x14) */
208104834Sobrien  xcoff_reloc_type_fail, /* R_RRTBA (0x15) */
209130561Sobrien  xcoff_reloc_type_ba,	 /* R_CAI   (0x16) */
210104834Sobrien  xcoff_reloc_type_crel, /* R_CREL  (0x17) */
211130561Sobrien  xcoff_reloc_type_ba,	 /* R_RBA   (0x18) */
212130561Sobrien  xcoff_reloc_type_ba,	 /* R_RBAC  (0x19) */
213104834Sobrien  xcoff64_reloc_type_br, /* R_RBR   (0x1a) */
214130561Sobrien  xcoff_reloc_type_ba,	 /* R_RBRC  (0x1b) */
215104834Sobrien};
216104834Sobrien
217104834Sobrien/* coffcode.h needs these to be defined.  */
21891041Sobrien/* Internalcoff.h and coffcode.h modify themselves based on these flags.  */
21991041Sobrien#define XCOFF64
22091041Sobrien#define RS6000COFF_C 1
22191041Sobrien
22291041Sobrien#define SELECT_RELOC(internal, howto)					\
22391041Sobrien  {									\
22491041Sobrien    internal.r_type = howto->type;					\
22591041Sobrien    internal.r_size =							\
22691041Sobrien      ((howto->complain_on_overflow == complain_overflow_signed		\
22791041Sobrien	? 0x80								\
22891041Sobrien	: 0)								\
22991041Sobrien       | (howto->bitsize - 1));						\
23091041Sobrien  }
23191041Sobrien
23291041Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
23391041Sobrien#define COFF_LONG_FILENAMES
23491041Sobrien#define NO_COFF_SYMBOLS
23591041Sobrien#define RTYPE2HOWTO(cache_ptr, dst) xcoff64_rtype2howto (cache_ptr, dst)
23691041Sobrien#define coff_mkobject _bfd_xcoff_mkobject
23791041Sobrien#define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
23891041Sobrien#define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
23991041Sobrien#define coff_bfd_reloc_type_lookup xcoff64_reloc_type_lookup
240218822Sdim#define coff_bfd_reloc_name_lookup xcoff64_reloc_name_lookup
24191041Sobrien#ifdef AIX_CORE
242130561Sobrienextern const bfd_target * rs6000coff_core_p
243130561Sobrien  PARAMS ((bfd *abfd));
244130561Sobrienextern bfd_boolean rs6000coff_core_file_matches_executable_p
245130561Sobrien  PARAMS ((bfd *cbfd, bfd *ebfd));
246130561Sobrienextern char *rs6000coff_core_file_failing_command
247130561Sobrien  PARAMS ((bfd *abfd));
248130561Sobrienextern int rs6000coff_core_file_failing_signal
249130561Sobrien  PARAMS ((bfd *abfd));
25091041Sobrien#define CORE_FILE_P rs6000coff_core_p
25191041Sobrien#define coff_core_file_failing_command \
25291041Sobrien  rs6000coff_core_file_failing_command
25391041Sobrien#define coff_core_file_failing_signal \
25491041Sobrien  rs6000coff_core_file_failing_signal
25591041Sobrien#define coff_core_file_matches_executable_p \
25691041Sobrien  rs6000coff_core_file_matches_executable_p
25791041Sobrien#else
25891041Sobrien#define CORE_FILE_P _bfd_dummy_target
25991041Sobrien#define coff_core_file_failing_command \
26091041Sobrien  _bfd_nocore_core_file_failing_command
26191041Sobrien#define coff_core_file_failing_signal \
26291041Sobrien  _bfd_nocore_core_file_failing_signal
26391041Sobrien#define coff_core_file_matches_executable_p \
26491041Sobrien  _bfd_nocore_core_file_matches_executable_p
26591041Sobrien#endif
26691041Sobrien#define coff_SWAP_sym_in _bfd_xcoff64_swap_sym_in
26791041Sobrien#define coff_SWAP_sym_out _bfd_xcoff64_swap_sym_out
26891041Sobrien#define coff_SWAP_aux_in _bfd_xcoff64_swap_aux_in
26991041Sobrien#define coff_SWAP_aux_out _bfd_xcoff64_swap_aux_out
270104834Sobrien#define coff_swap_reloc_in xcoff64_swap_reloc_in
271104834Sobrien#define coff_swap_reloc_out xcoff64_swap_reloc_out
272104834Sobrien#define NO_COFF_RELOCS
27391041Sobrien
27491041Sobrien#include "coffcode.h"
27591041Sobrien
27691041Sobrien/* For XCOFF64, the effective width of symndx changes depending on
27791041Sobrien   whether we are the first entry.  Sigh.  */
27891041Sobrienstatic void
27991041Sobrien_bfd_xcoff64_swap_lineno_in (abfd, ext1, in1)
28091041Sobrien     bfd *abfd;
28191041Sobrien     PTR ext1;
28291041Sobrien     PTR in1;
28391041Sobrien{
28491041Sobrien  LINENO *ext = (LINENO *) ext1;
28591041Sobrien  struct internal_lineno *in = (struct internal_lineno *) in1;
28691041Sobrien
28791041Sobrien  in->l_lnno = H_GET_32 (abfd, (ext->l_lnno));
28891041Sobrien  if (in->l_lnno == 0)
28991041Sobrien    in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx);
29091041Sobrien  else
29191041Sobrien    in->l_addr.l_paddr = H_GET_64 (abfd, ext->l_addr.l_paddr);
29291041Sobrien}
29391041Sobrien
29491041Sobrienstatic unsigned int
29591041Sobrien_bfd_xcoff64_swap_lineno_out (abfd, inp, outp)
29691041Sobrien     bfd *abfd;
29791041Sobrien     PTR inp;
29891041Sobrien     PTR outp;
29991041Sobrien{
30091041Sobrien  struct internal_lineno *in = (struct internal_lineno *) inp;
30191041Sobrien  struct external_lineno *ext = (struct external_lineno *) outp;
30291041Sobrien
30391041Sobrien  H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx);
30491041Sobrien  H_PUT_32 (abfd, in->l_lnno, (ext->l_lnno));
30591041Sobrien
30691041Sobrien  if (in->l_lnno == 0)
30791041Sobrien    H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx);
30891041Sobrien  else
30991041Sobrien    H_PUT_64 (abfd, in->l_addr.l_paddr, ext->l_addr.l_paddr);
31091041Sobrien
31191041Sobrien  return bfd_coff_linesz (abfd);
31291041Sobrien}
31391041Sobrien
31491041Sobrienstatic void
31591041Sobrien_bfd_xcoff64_swap_sym_in (abfd, ext1, in1)
31691041Sobrien     bfd *abfd;
31791041Sobrien     PTR ext1;
31891041Sobrien     PTR in1;
31991041Sobrien{
32091041Sobrien  struct external_syment *ext = (struct external_syment *) ext1;
32191041Sobrien  struct internal_syment *in = (struct internal_syment *) in1;
32291041Sobrien
32391041Sobrien  in->_n._n_n._n_zeroes = 0;
32491041Sobrien  in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e_offset);
32591041Sobrien  in->n_value = H_GET_64 (abfd, ext->e_value);
32691041Sobrien  in->n_scnum = H_GET_16 (abfd, ext->e_scnum);
32791041Sobrien  in->n_type = H_GET_16 (abfd, ext->e_type);
32891041Sobrien  in->n_sclass = H_GET_8 (abfd, ext->e_sclass);
32991041Sobrien  in->n_numaux = H_GET_8 (abfd, ext->e_numaux);
33091041Sobrien}
33191041Sobrien
33291041Sobrienstatic unsigned int
33391041Sobrien_bfd_xcoff64_swap_sym_out (abfd, inp, extp)
33491041Sobrien     bfd *abfd;
33591041Sobrien     PTR inp;
33691041Sobrien     PTR extp;
33791041Sobrien{
33891041Sobrien  struct internal_syment *in = (struct internal_syment *) inp;
33991041Sobrien  struct external_syment *ext = (struct external_syment *) extp;
34091041Sobrien
34191041Sobrien  H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e_offset);
34291041Sobrien  H_PUT_64 (abfd, in->n_value, ext->e_value);
34391041Sobrien  H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);
34491041Sobrien  H_PUT_16 (abfd, in->n_type, ext->e_type);
34591041Sobrien  H_PUT_8 (abfd, in->n_sclass, ext->e_sclass);
34691041Sobrien  H_PUT_8 (abfd, in->n_numaux, ext->e_numaux);
34791041Sobrien  return bfd_coff_symesz (abfd);
34891041Sobrien}
34991041Sobrien
35091041Sobrienstatic void
35191041Sobrien_bfd_xcoff64_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
35291041Sobrien     bfd *abfd;
35391041Sobrien     PTR ext1;
35491041Sobrien     int type;
35591041Sobrien     int class;
35691041Sobrien     int indx;
35791041Sobrien     int numaux;
35891041Sobrien     PTR in1;
35991041Sobrien{
36091041Sobrien  union external_auxent *ext = (union external_auxent *) ext1;
36191041Sobrien  union internal_auxent *in = (union internal_auxent *) in1;
36291041Sobrien
36391041Sobrien  switch (class)
36491041Sobrien    {
36591041Sobrien    case C_FILE:
366104834Sobrien      if (ext->x_file.x_n.x_zeroes[0] == 0)
36791041Sobrien	{
36891041Sobrien	  in->x_file.x_n.x_zeroes = 0;
36991041Sobrien	  in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
37091041Sobrien	}
37191041Sobrien      else
37291041Sobrien	{
37391041Sobrien	  memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
37491041Sobrien	}
37591041Sobrien      goto end;
37691041Sobrien
37791041Sobrien      /* RS/6000 "csect" auxents */
37891041Sobrien    case C_EXT:
37991041Sobrien    case C_HIDEXT:
38091041Sobrien      if (indx + 1 == numaux)
38191041Sobrien	{
38291041Sobrien	  bfd_signed_vma h = 0;
38391041Sobrien	  bfd_vma l = 0;
38491041Sobrien
38591041Sobrien	  h = H_GET_S32 (abfd, ext->x_csect.x_scnlen_hi);
38691041Sobrien	  l = H_GET_32 (abfd, ext->x_csect.x_scnlen_lo);
38791041Sobrien
38891041Sobrien	  in->x_csect.x_scnlen.l = h << 32 | (l & 0xffffffff);
38991041Sobrien
39091041Sobrien	  in->x_csect.x_parmhash = H_GET_32 (abfd, ext->x_csect.x_parmhash);
39191041Sobrien	  in->x_csect.x_snhash = H_GET_16 (abfd, ext->x_csect.x_snhash);
39291041Sobrien	  /* We don't have to hack bitfields in x_smtyp because it's
39391041Sobrien	     defined by shifts-and-ands, which are equivalent on all
39491041Sobrien	     byte orders.  */
39591041Sobrien	  in->x_csect.x_smtyp = H_GET_8 (abfd, ext->x_csect.x_smtyp);
39691041Sobrien	  in->x_csect.x_smclas = H_GET_8 (abfd, ext->x_csect.x_smclas);
39791041Sobrien	  goto end;
39891041Sobrien	}
39991041Sobrien      break;
40091041Sobrien
40191041Sobrien    case C_STAT:
40291041Sobrien    case C_LEAFSTAT:
40391041Sobrien    case C_HIDDEN:
40491041Sobrien      if (type == T_NULL)
40591041Sobrien	{
40691041Sobrien	  /* PE defines some extra fields; we zero them out for
40791041Sobrien	     safety.  */
40891041Sobrien	  in->x_scn.x_checksum = 0;
40991041Sobrien	  in->x_scn.x_associated = 0;
41091041Sobrien	  in->x_scn.x_comdat = 0;
41191041Sobrien
41291041Sobrien	  goto end;
41391041Sobrien	}
41491041Sobrien      break;
41591041Sobrien    }
41691041Sobrien
41791041Sobrien  if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
41891041Sobrien    {
41991041Sobrien      in->x_sym.x_fcnary.x_fcn.x_lnnoptr
42091041Sobrien	= H_GET_64 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
42191041Sobrien      in->x_sym.x_fcnary.x_fcn.x_endndx.l
42291041Sobrien	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx);
42391041Sobrien    }
42491041Sobrien  if (ISFCN (type))
42591041Sobrien    {
42691041Sobrien      in->x_sym.x_misc.x_fsize
42791041Sobrien	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_fsize);
42891041Sobrien    }
42991041Sobrien  else
43091041Sobrien    {
43191041Sobrien      in->x_sym.x_misc.x_lnsz.x_lnno
43291041Sobrien	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_lnsz.x_lnno);
43391041Sobrien      in->x_sym.x_misc.x_lnsz.x_size
43491041Sobrien	= H_GET_16 (abfd, ext->x_sym.x_fcnary.x_lnsz.x_size);
43591041Sobrien    }
43691041Sobrien
43791041Sobrien end: ;
43891041Sobrien}
43991041Sobrien
44091041Sobrienstatic unsigned int
44191041Sobrien_bfd_xcoff64_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
44291041Sobrien     bfd *abfd;
44391041Sobrien     PTR inp;
44491041Sobrien     int type;
44591041Sobrien     int class;
44691041Sobrien     int indx ATTRIBUTE_UNUSED;
44791041Sobrien     int numaux ATTRIBUTE_UNUSED;
44891041Sobrien     PTR extp;
44991041Sobrien{
45091041Sobrien  union internal_auxent *in = (union internal_auxent *) inp;
45191041Sobrien  union external_auxent *ext = (union external_auxent *) extp;
45291041Sobrien
45391041Sobrien  memset ((PTR) ext, 0, bfd_coff_auxesz (abfd));
45491041Sobrien  switch (class)
45591041Sobrien    {
45691041Sobrien    case C_FILE:
457104834Sobrien      if (in->x_file.x_n.x_zeroes == 0)
45891041Sobrien	{
45991041Sobrien	  H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
46091041Sobrien	  H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
46191041Sobrien	}
46291041Sobrien      else
46391041Sobrien	{
46491041Sobrien	  memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
46591041Sobrien	}
46691041Sobrien      H_PUT_8 (abfd, _AUX_FILE, ext->x_auxtype.x_auxtype);
46791041Sobrien      goto end;
46891041Sobrien
46991041Sobrien      /* RS/6000 "csect" auxents */
47091041Sobrien    case C_EXT:
47191041Sobrien    case C_HIDEXT:
47291041Sobrien      if (indx + 1 == numaux)
47391041Sobrien	{
47491041Sobrien	  bfd_vma temp;
47591041Sobrien
47691041Sobrien	  temp = in->x_csect.x_scnlen.l & 0xffffffff;
47791041Sobrien	  H_PUT_32 (abfd, temp, ext->x_csect.x_scnlen_lo);
47891041Sobrien	  temp = in->x_csect.x_scnlen.l >> 32;
47991041Sobrien	  H_PUT_32 (abfd, temp, ext->x_csect.x_scnlen_hi);
48091041Sobrien	  H_PUT_32 (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
48191041Sobrien	  H_PUT_16 (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
48291041Sobrien	  /* We don't have to hack bitfields in x_smtyp because it's
48391041Sobrien	     defined by shifts-and-ands, which are equivalent on all
48491041Sobrien	     byte orders.  */
48591041Sobrien	  H_PUT_8 (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
48691041Sobrien	  H_PUT_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
48791041Sobrien	  H_PUT_8 (abfd, _AUX_CSECT, ext->x_auxtype.x_auxtype);
48891041Sobrien	  goto end;
48991041Sobrien	}
49091041Sobrien      break;
49191041Sobrien
49291041Sobrien    case C_STAT:
49391041Sobrien    case C_LEAFSTAT:
49491041Sobrien    case C_HIDDEN:
49591041Sobrien      if (type == T_NULL)
49691041Sobrien	{
49791041Sobrien	  goto end;
49891041Sobrien	}
49991041Sobrien      break;
50091041Sobrien    }
50191041Sobrien
50291041Sobrien  if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
50391041Sobrien    {
50491041Sobrien      H_PUT_64 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
50591041Sobrien	       ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
50691041Sobrien      H_PUT_8 (abfd, _AUX_FCN,
50791041Sobrien	       ext->x_auxtype.x_auxtype);
50891041Sobrien      H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
50991041Sobrien	       ext->x_sym.x_fcnary.x_fcn.x_endndx);
51091041Sobrien    }
51191041Sobrien  if (ISFCN (type))
51291041Sobrien    {
51391041Sobrien      H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize,
51491041Sobrien	       ext->x_sym.x_fcnary.x_fcn.x_fsize);
51591041Sobrien    }
51691041Sobrien  else
51791041Sobrien    {
51891041Sobrien      H_PUT_32 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
51991041Sobrien	       ext->x_sym.x_fcnary.x_lnsz.x_lnno);
52091041Sobrien      H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_size,
52191041Sobrien	       ext->x_sym.x_fcnary.x_lnsz.x_size);
52291041Sobrien    }
52391041Sobrien
52491041Sobrien end:
52591041Sobrien
52691041Sobrien  return bfd_coff_auxesz (abfd);
52791041Sobrien}
52891041Sobrien
529130561Sobrienstatic bfd_boolean
530104834Sobrien_bfd_xcoff64_put_symbol_name (abfd, strtab, sym, name)
531104834Sobrien     bfd *abfd;
532104834Sobrien     struct bfd_strtab_hash *strtab;
533104834Sobrien     struct internal_syment *sym;
534104834Sobrien     const char *name;
535104834Sobrien{
536130561Sobrien  bfd_boolean hash;
53791041Sobrien  bfd_size_type indx;
53891041Sobrien
539130561Sobrien  hash = TRUE;
54091041Sobrien
54191041Sobrien  if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
542130561Sobrien    hash = FALSE;
54391041Sobrien
544130561Sobrien  indx = _bfd_stringtab_add (strtab, name, hash, FALSE);
54591041Sobrien
54691041Sobrien  if (indx == (bfd_size_type) -1)
547130561Sobrien    return FALSE;
54891041Sobrien
54991041Sobrien  sym->_n._n_n._n_zeroes = 0;
55091041Sobrien  sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx;
55191041Sobrien
552130561Sobrien  return TRUE;
55391041Sobrien}
55491041Sobrien
555130561Sobrienstatic bfd_boolean
55691041Sobrien_bfd_xcoff64_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
55791041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
55891041Sobrien     struct xcoff_loader_info *ldinfo;
55991041Sobrien     struct internal_ldsym *ldsym;
56091041Sobrien     const char *name;
56191041Sobrien{
56291041Sobrien  size_t len;
56391041Sobrien  len = strlen (name);
56491041Sobrien
56591041Sobrien  if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
56691041Sobrien    {
56791041Sobrien      bfd_size_type newalc;
568218822Sdim      char *newstrings;
56991041Sobrien
57091041Sobrien      newalc = ldinfo->string_alc * 2;
57191041Sobrien      if (newalc == 0)
57291041Sobrien	newalc = 32;
57391041Sobrien      while (ldinfo->string_size + len + 3 > newalc)
57491041Sobrien	newalc *= 2;
57591041Sobrien
576218822Sdim      newstrings = bfd_realloc (ldinfo->strings, newalc);
57791041Sobrien      if (newstrings == NULL)
57891041Sobrien	{
579130561Sobrien	  ldinfo->failed = TRUE;
580130561Sobrien	  return FALSE;
58191041Sobrien	}
58291041Sobrien      ldinfo->string_alc = newalc;
58391041Sobrien      ldinfo->strings = newstrings;
58491041Sobrien    }
58591041Sobrien
58691041Sobrien  bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1),
58791041Sobrien	      ldinfo->strings + ldinfo->string_size);
58891041Sobrien  strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
58991041Sobrien  ldsym->_l._l_l._l_zeroes = 0;
59091041Sobrien  ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
59191041Sobrien  ldinfo->string_size += len + 3;
59291041Sobrien
593130561Sobrien  return TRUE;
59491041Sobrien}
59591041Sobrien
59691041Sobrien/* Routines to swap information in the XCOFF .loader section.  If we
59791041Sobrien   ever need to write an XCOFF loader, this stuff will need to be
59891041Sobrien   moved to another file shared by the linker (which XCOFF calls the
59991041Sobrien   ``binder'') and the loader.  */
60091041Sobrien
60191041Sobrien/* Swap in the ldhdr structure.  */
60291041Sobrien
60391041Sobrienstatic void
60491041Sobrienxcoff64_swap_ldhdr_in (abfd, s, dst)
60591041Sobrien     bfd *abfd;
60691041Sobrien     const PTR s;
60791041Sobrien     struct internal_ldhdr *dst;
60891041Sobrien{
60991041Sobrien  const struct external_ldhdr *src = (const struct external_ldhdr *) s;
61091041Sobrien
61191041Sobrien  dst->l_version = bfd_get_32 (abfd, src->l_version);
61291041Sobrien  dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
61391041Sobrien  dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
61491041Sobrien  dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
61591041Sobrien  dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
61691041Sobrien  dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
61791041Sobrien  dst->l_impoff = bfd_get_64 (abfd, src->l_impoff);
61891041Sobrien  dst->l_stoff = bfd_get_64 (abfd, src->l_stoff);
61991041Sobrien  dst->l_symoff = bfd_get_64 (abfd, src->l_symoff);
62091041Sobrien  dst->l_rldoff = bfd_get_64 (abfd, src->l_rldoff);
62191041Sobrien}
62291041Sobrien
62391041Sobrien/* Swap out the ldhdr structure.  */
62491041Sobrien
62591041Sobrienstatic void
62691041Sobrienxcoff64_swap_ldhdr_out (abfd, src, d)
62791041Sobrien     bfd *abfd;
62891041Sobrien     const struct internal_ldhdr *src;
62991041Sobrien     PTR d;
63091041Sobrien{
63191041Sobrien  struct external_ldhdr *dst = (struct external_ldhdr *) d;
63291041Sobrien
63391041Sobrien  bfd_put_32 (abfd, (bfd_vma) src->l_version, dst->l_version);
63491041Sobrien  bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
63591041Sobrien  bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
63691041Sobrien  bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
63791041Sobrien  bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
63891041Sobrien  bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
63991041Sobrien  bfd_put_64 (abfd, src->l_impoff, dst->l_impoff);
64091041Sobrien  bfd_put_64 (abfd, src->l_stoff, dst->l_stoff);
64191041Sobrien  bfd_put_64 (abfd, src->l_symoff, dst->l_symoff);
64291041Sobrien  bfd_put_64 (abfd, src->l_rldoff, dst->l_rldoff);
64391041Sobrien}
64491041Sobrien
64591041Sobrien/* Swap in the ldsym structure.  */
64691041Sobrien
64791041Sobrienstatic void
64891041Sobrienxcoff64_swap_ldsym_in (abfd, s, dst)
64991041Sobrien     bfd *abfd;
65091041Sobrien     const PTR s;
65191041Sobrien     struct internal_ldsym *dst;
65291041Sobrien{
65391041Sobrien  const struct external_ldsym *src = (const struct external_ldsym *) s;
65491041Sobrien  /* XCOFF64 does not use l_zeroes like XCOFF32
65591041Sobrien     Set the internal l_zeroes to 0 so the common 32/64 code uses l_value
65691041Sobrien     as an offset into the loader symbol table.  */
65791041Sobrien  dst->_l._l_l._l_zeroes = 0;
65891041Sobrien  dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->l_offset);
65991041Sobrien  dst->l_value = bfd_get_64 (abfd, src->l_value);
66091041Sobrien  dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
66191041Sobrien  dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
66291041Sobrien  dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
66391041Sobrien  dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
66491041Sobrien  dst->l_parm = bfd_get_32 (abfd, src->l_parm);
66591041Sobrien}
66691041Sobrien
66791041Sobrien/* Swap out the ldsym structure.  */
66891041Sobrien
66991041Sobrienstatic void
67091041Sobrienxcoff64_swap_ldsym_out (abfd, src, d)
67191041Sobrien     bfd *abfd;
67291041Sobrien     const struct internal_ldsym *src;
67391041Sobrien     PTR d;
67491041Sobrien{
67591041Sobrien  struct external_ldsym *dst = (struct external_ldsym *) d;
67691041Sobrien
67791041Sobrien  bfd_put_64 (abfd, src->l_value, dst->l_value);
67891041Sobrien  bfd_put_32 (abfd, (bfd_vma) src->_l._l_l._l_offset, dst->l_offset);
67991041Sobrien  bfd_put_16 (abfd, (bfd_vma) src->l_scnum, dst->l_scnum);
68091041Sobrien  bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
68191041Sobrien  bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
68291041Sobrien  bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
68391041Sobrien  bfd_put_32 (abfd, src->l_parm, dst->l_parm);
68491041Sobrien}
68591041Sobrien
686104834Sobrienstatic void
687104834Sobrienxcoff64_swap_reloc_in (abfd, s, d)
688104834Sobrien     bfd *abfd;
689104834Sobrien     PTR s;
690104834Sobrien     PTR d;
691104834Sobrien{
692104834Sobrien  struct external_reloc *src = (struct external_reloc *) s;
693104834Sobrien  struct internal_reloc *dst = (struct internal_reloc *) d;
694104834Sobrien
695104834Sobrien  memset (dst, 0, sizeof (struct internal_reloc));
696104834Sobrien
697104834Sobrien  dst->r_vaddr = bfd_get_64 (abfd, src->r_vaddr);
698104834Sobrien  dst->r_symndx = bfd_get_32 (abfd, src->r_symndx);
699104834Sobrien  dst->r_size = bfd_get_8 (abfd, src->r_size);
700104834Sobrien  dst->r_type = bfd_get_8 (abfd, src->r_type);
701104834Sobrien}
702104834Sobrien
703104834Sobrienstatic unsigned int
704104834Sobrienxcoff64_swap_reloc_out (abfd, s, d)
705104834Sobrien     bfd *abfd;
706104834Sobrien     PTR s;
707104834Sobrien     PTR d;
708104834Sobrien{
709104834Sobrien  struct internal_reloc *src = (struct internal_reloc *) s;
710104834Sobrien  struct external_reloc *dst = (struct external_reloc *) d;
711104834Sobrien
712104834Sobrien  bfd_put_64 (abfd, src->r_vaddr, dst->r_vaddr);
713104834Sobrien  bfd_put_32 (abfd, src->r_symndx, dst->r_symndx);
714104834Sobrien  bfd_put_8 (abfd, src->r_type, dst->r_type);
715104834Sobrien  bfd_put_8 (abfd, src->r_size, dst->r_size);
716104834Sobrien
717104834Sobrien  return bfd_coff_relsz (abfd);
718104834Sobrien}
719104834Sobrien
72091041Sobrien/* Swap in the ldrel structure.  */
72191041Sobrien
72291041Sobrienstatic void
72391041Sobrienxcoff64_swap_ldrel_in (abfd, s, dst)
72491041Sobrien     bfd *abfd;
72591041Sobrien     const PTR s;
72691041Sobrien     struct internal_ldrel *dst;
72791041Sobrien{
72891041Sobrien  const struct external_ldrel *src = (const struct external_ldrel *) s;
72991041Sobrien
73091041Sobrien  dst->l_vaddr = bfd_get_64 (abfd, src->l_vaddr);
73191041Sobrien  dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
73291041Sobrien  dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
73391041Sobrien  dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
73491041Sobrien}
73591041Sobrien
73691041Sobrien/* Swap out the ldrel structure.  */
73791041Sobrien
73891041Sobrienstatic void
73991041Sobrienxcoff64_swap_ldrel_out (abfd, src, d)
74091041Sobrien     bfd *abfd;
74191041Sobrien     const struct internal_ldrel *src;
74291041Sobrien     PTR d;
74391041Sobrien{
74491041Sobrien  struct external_ldrel *dst = (struct external_ldrel *) d;
74591041Sobrien
74691041Sobrien  bfd_put_64 (abfd, src->l_vaddr, dst->l_vaddr);
74791041Sobrien  bfd_put_16 (abfd, (bfd_vma) src->l_rtype, dst->l_rtype);
74891041Sobrien  bfd_put_16 (abfd, (bfd_vma) src->l_rsecnm, dst->l_rsecnm);
74991041Sobrien  bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
75091041Sobrien}
75191041Sobrien
752130561Sobrienstatic bfd_boolean
75391041Sobrienxcoff64_write_object_contents (abfd)
754130561Sobrien     bfd *abfd;
75591041Sobrien{
75691041Sobrien  asection *current;
757130561Sobrien  bfd_boolean hasrelocs = FALSE;
758130561Sobrien  bfd_boolean haslinno = FALSE;
75991041Sobrien  file_ptr scn_base;
76091041Sobrien  file_ptr reloc_base;
76191041Sobrien  file_ptr lineno_base;
76291041Sobrien  file_ptr sym_base;
76391041Sobrien  unsigned long reloc_size = 0;
76491041Sobrien  unsigned long lnno_size = 0;
765130561Sobrien  bfd_boolean long_section_names;
76691041Sobrien  asection *text_sec = ((void *) 0);
76791041Sobrien  asection *data_sec = ((void *) 0);
76891041Sobrien  asection *bss_sec = ((void *) 0);
76991041Sobrien  struct internal_filehdr internal_f;
77091041Sobrien  struct internal_aouthdr internal_a;
77191041Sobrien
77291041Sobrien  bfd_set_error (bfd_error_system_call);
77391041Sobrien
774104834Sobrien  if (! abfd->output_has_begun)
77591041Sobrien    {
77691041Sobrien      if (! bfd_coff_compute_section_file_positions (abfd))
777130561Sobrien	return FALSE;
77891041Sobrien    }
77991041Sobrien
780104834Sobrien  /* Work out the size of the reloc and linno areas.  */
78191041Sobrien  reloc_base = obj_relocbase (abfd);
78291041Sobrien
78391041Sobrien  for (current = abfd->sections; current != NULL; current = current->next)
78491041Sobrien    reloc_size += current->reloc_count * bfd_coff_relsz (abfd);
78591041Sobrien
78691041Sobrien  lineno_base = reloc_base + reloc_size;
78791041Sobrien
78891041Sobrien  /* Make a pass through the symbol table to count line number entries and
789104834Sobrien     put them into the correct asections.  */
79091041Sobrien  lnno_size = coff_count_linenumbers (abfd) * bfd_coff_linesz (abfd);
79191041Sobrien
79291041Sobrien  sym_base = lineno_base + lnno_size;
79391041Sobrien
794104834Sobrien  /* Indicate in each section->line_filepos its actual file address.  */
79591041Sobrien  for (current = abfd->sections; current != NULL; current =  current->next)
79691041Sobrien    {
79791041Sobrien      if (current->lineno_count)
79891041Sobrien	{
79991041Sobrien	  current->line_filepos = lineno_base;
80091041Sobrien	  current->moving_line_filepos = lineno_base;
80191041Sobrien	  lineno_base += current->lineno_count * bfd_coff_linesz (abfd);
80291041Sobrien	}
80391041Sobrien      else
80491041Sobrien	{
80591041Sobrien	  current->line_filepos = 0;
80691041Sobrien	}
80791041Sobrien
80891041Sobrien      if (current->reloc_count)
80991041Sobrien	{
81091041Sobrien	  current->rel_filepos = reloc_base;
81191041Sobrien	  reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
81291041Sobrien	}
81391041Sobrien      else
81491041Sobrien	{
81591041Sobrien	  current->rel_filepos = 0;
81691041Sobrien	}
81791041Sobrien    }
81891041Sobrien
81991041Sobrien  if ((abfd->flags & EXEC_P) != 0)
82091041Sobrien    {
82191041Sobrien      scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
82291041Sobrien      internal_f.f_opthdr = bfd_coff_aoutsz (abfd);
82391041Sobrien    }
82491041Sobrien  else
82591041Sobrien    {
82691041Sobrien      scn_base = bfd_coff_filhsz (abfd);
82791041Sobrien      internal_f.f_opthdr = 0;
82891041Sobrien    }
82991041Sobrien
83091041Sobrien  internal_f.f_nscns = 0;
83191041Sobrien
83291041Sobrien  if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
833130561Sobrien    return FALSE;
83491041Sobrien
835130561Sobrien  long_section_names = FALSE;
83691041Sobrien  for (current = abfd->sections; current != NULL; current = current->next)
83791041Sobrien    {
83891041Sobrien      struct internal_scnhdr section;
83991041Sobrien      struct external_scnhdr buff;
84091041Sobrien      bfd_size_type amount;
84191041Sobrien
84291041Sobrien      internal_f.f_nscns++;
84391041Sobrien
84491041Sobrien      strncpy (section.s_name, current->name, SCNNMLEN);
84591041Sobrien
84691041Sobrien      section.s_vaddr = current->vma;
84791041Sobrien      section.s_paddr = current->lma;
848218822Sdim      section.s_size =  current->size;
84991041Sobrien
85091041Sobrien      /* If this section has no size or is unloadable then the scnptr
85191041Sobrien	 will be 0 too.  */
852218822Sdim      if (current->size == 0
85391041Sobrien	  || (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
85491041Sobrien	{
85591041Sobrien	  section.s_scnptr = 0;
85691041Sobrien	}
85791041Sobrien      else
85891041Sobrien	{
85991041Sobrien	  section.s_scnptr = current->filepos;
86091041Sobrien	}
86191041Sobrien
86291041Sobrien      section.s_relptr = current->rel_filepos;
86391041Sobrien      section.s_lnnoptr = current->line_filepos;
86491041Sobrien      section.s_nreloc = current->reloc_count;
86591041Sobrien
86691041Sobrien      section.s_nlnno = current->lineno_count;
86791041Sobrien      if (current->reloc_count != 0)
868130561Sobrien	hasrelocs = TRUE;
86991041Sobrien      if (current->lineno_count != 0)
870130561Sobrien	haslinno = TRUE;
87191041Sobrien
87291041Sobrien      section.s_flags = sec_to_styp_flags (current->name, current->flags);
87391041Sobrien
87491041Sobrien      if (!strcmp (current->name, _TEXT))
87591041Sobrien	{
87691041Sobrien	  text_sec = current;
87791041Sobrien	}
87891041Sobrien      else if (!strcmp (current->name, _DATA))
87991041Sobrien	{
88091041Sobrien	  data_sec = current;
88191041Sobrien	}
88291041Sobrien      else if (!strcmp (current->name, _BSS))
88391041Sobrien	{
88491041Sobrien	  bss_sec = current;
88591041Sobrien	}
88691041Sobrien
88791041Sobrien      amount = bfd_coff_scnhsz (abfd);
88891041Sobrien      if (bfd_coff_swap_scnhdr_out (abfd, &section, &buff) == 0
88991041Sobrien	  || bfd_bwrite ((PTR) (&buff), amount, abfd) != amount)
890130561Sobrien	return FALSE;
89191041Sobrien    }
89291041Sobrien
89391041Sobrien  internal_f.f_timdat = 0;
89491041Sobrien
89591041Sobrien  internal_f.f_flags = 0;
89691041Sobrien
89791041Sobrien  if (!hasrelocs)
89891041Sobrien    internal_f.f_flags |= F_RELFLG;
89991041Sobrien  if (!haslinno)
90091041Sobrien    internal_f.f_flags |= F_LNNO;
90191041Sobrien  if (abfd->flags & EXEC_P)
90291041Sobrien    internal_f.f_flags |= F_EXEC;
90391041Sobrien
904104834Sobrien  /* FIXME: this is wrong for PPC_PE!  */
90591041Sobrien  if (bfd_little_endian (abfd))
90691041Sobrien    internal_f.f_flags |= F_AR32WR;
90791041Sobrien  else
90891041Sobrien    internal_f.f_flags |= F_AR32W;
90991041Sobrien
91091041Sobrien  if ((abfd->flags & DYNAMIC) != 0)
91191041Sobrien    internal_f.f_flags |= F_SHROBJ;
91291041Sobrien  if (bfd_get_section_by_name (abfd, _LOADER) != NULL)
91391041Sobrien    internal_f.f_flags |= F_DYNLOAD;
91491041Sobrien
91591041Sobrien  memset (&internal_a, 0, sizeof internal_a);
91691041Sobrien
917104834Sobrien  internal_f.f_magic = bfd_xcoff_magic_number (abfd);
918104834Sobrien  internal_a.magic = (abfd->flags & D_PAGED
919104834Sobrien		      ? RS6K_AOUTHDR_ZMAGIC
920104834Sobrien		      : (abfd->flags & WP_TEXT
921104834Sobrien			 ? RS6K_AOUTHDR_NMAGIC
922104834Sobrien			 : RS6K_AOUTHDR_OMAGIC));
92391041Sobrien
92491041Sobrien  /* FIXME: Does anybody ever set this to another value?  */
92591041Sobrien  internal_a.vstamp = 0;
92691041Sobrien
927104834Sobrien  /* Now should write relocs, strings, syms.  */
92891041Sobrien  obj_sym_filepos (abfd) = sym_base;
92991041Sobrien
93091041Sobrien  internal_f.f_symptr = 0;
93191041Sobrien  internal_f.f_nsyms = 0;
93291041Sobrien
93391041Sobrien  /* If bfd_get_symcount (abfd) != 0, then we are not using the COFF
93491041Sobrien     backend linker, and obj_raw_syment_count is not valid until after
93591041Sobrien     coff_write_symbols is called.  */
93691041Sobrien  if (bfd_get_symcount (abfd) != 0)
93791041Sobrien    {
93891041Sobrien      int firstundef;
93991041Sobrien
94091041Sobrien      if (!coff_renumber_symbols (abfd, &firstundef))
941130561Sobrien	return FALSE;
94291041Sobrien      coff_mangle_symbols (abfd);
94391041Sobrien      if (! coff_write_symbols (abfd))
944130561Sobrien	return FALSE;
94591041Sobrien      if (! coff_write_linenumbers (abfd))
946130561Sobrien	return FALSE;
94791041Sobrien      if (! coff_write_relocs (abfd, firstundef))
948130561Sobrien	return FALSE;
94991041Sobrien
95091041Sobrien      internal_f.f_symptr = sym_base;
95191041Sobrien      internal_f.f_nsyms = bfd_get_symcount (abfd);
95291041Sobrien    }
95391041Sobrien  else if (obj_raw_syment_count (abfd) != 0)
95491041Sobrien    {
95591041Sobrien      internal_f.f_symptr = sym_base;
95691041Sobrien
95791041Sobrien      /* AIX appears to require that F_RELFLG not be set if there are
95891041Sobrien	 local symbols but no relocations.  */
95991041Sobrien      internal_f.f_flags &=~ F_RELFLG;
96091041Sobrien    }
96191041Sobrien  else
96291041Sobrien    {
96391041Sobrien      internal_f.f_flags |= F_LSYMS;
96491041Sobrien    }
96591041Sobrien
96691041Sobrien  if (text_sec)
96791041Sobrien    {
968218822Sdim      internal_a.tsize = text_sec->size;
96991041Sobrien      internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
97091041Sobrien    }
97191041Sobrien
97291041Sobrien  if (data_sec)
97391041Sobrien    {
974218822Sdim      internal_a.dsize = data_sec->size;
97591041Sobrien      internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
97691041Sobrien    }
97791041Sobrien
97891041Sobrien  if (bss_sec)
97991041Sobrien    {
980218822Sdim      internal_a.bsize = bss_sec->size;
98191041Sobrien      if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
98291041Sobrien	internal_a.data_start = bss_sec->vma;
98391041Sobrien    }
98491041Sobrien
98591041Sobrien  internal_a.entry = bfd_get_start_address (abfd);
98691041Sobrien  internal_f.f_nsyms = obj_raw_syment_count (abfd);
98791041Sobrien
98891041Sobrien  if (xcoff_data (abfd)->full_aouthdr)
98991041Sobrien    {
99091041Sobrien      bfd_vma toc;
99191041Sobrien      asection *loader_sec;
99291041Sobrien
99391041Sobrien      internal_a.vstamp = 1;
99491041Sobrien
99591041Sobrien      internal_a.o_snentry = xcoff_data (abfd)->snentry;
99691041Sobrien      if (internal_a.o_snentry == 0)
99791041Sobrien	internal_a.entry = (bfd_vma) -1;
99891041Sobrien
99991041Sobrien      if (text_sec != NULL)
100091041Sobrien	{
100191041Sobrien	  internal_a.o_sntext = text_sec->target_index;
100291041Sobrien	  internal_a.o_algntext = bfd_get_section_alignment (abfd, text_sec);
100391041Sobrien	}
100491041Sobrien      else
100591041Sobrien	{
100691041Sobrien	  internal_a.o_sntext = 0;
100791041Sobrien	  internal_a.o_algntext = 0;
100891041Sobrien	}
100991041Sobrien
101091041Sobrien      if (data_sec != NULL)
101191041Sobrien	{
101291041Sobrien	  internal_a.o_sndata = data_sec->target_index;
101391041Sobrien	  internal_a.o_algndata = bfd_get_section_alignment (abfd, data_sec);
101491041Sobrien	}
101591041Sobrien      else
101691041Sobrien	{
101791041Sobrien	  internal_a.o_sndata = 0;
101891041Sobrien	  internal_a.o_algndata = 0;
101991041Sobrien	}
102091041Sobrien
102191041Sobrien      loader_sec = bfd_get_section_by_name (abfd, ".loader");
102291041Sobrien      if (loader_sec != NULL)
102391041Sobrien	internal_a.o_snloader = loader_sec->target_index;
102491041Sobrien      else
102591041Sobrien	internal_a.o_snloader = 0;
102691041Sobrien      if (bss_sec != NULL)
102791041Sobrien	internal_a.o_snbss = bss_sec->target_index;
102891041Sobrien      else
102991041Sobrien	internal_a.o_snbss = 0;
103091041Sobrien
103191041Sobrien      toc = xcoff_data (abfd)->toc;
103291041Sobrien      internal_a.o_toc = toc;
103391041Sobrien      internal_a.o_sntoc = xcoff_data (abfd)->sntoc;
103491041Sobrien
103591041Sobrien      internal_a.o_modtype = xcoff_data (abfd)->modtype;
103691041Sobrien      if (xcoff_data (abfd)->cputype != -1)
103791041Sobrien	internal_a.o_cputype = xcoff_data (abfd)->cputype;
103891041Sobrien      else
103991041Sobrien	{
104091041Sobrien	  switch (bfd_get_arch (abfd))
104191041Sobrien	    {
104291041Sobrien	    case bfd_arch_rs6000:
104391041Sobrien	      internal_a.o_cputype = 4;
104491041Sobrien	      break;
104591041Sobrien	    case bfd_arch_powerpc:
1046130561Sobrien	      if (bfd_get_mach (abfd) == bfd_mach_ppc)
104791041Sobrien		internal_a.o_cputype = 3;
104891041Sobrien	      else
104991041Sobrien		internal_a.o_cputype = 1;
105091041Sobrien	      break;
105191041Sobrien	    default:
105291041Sobrien	      abort ();
105391041Sobrien	    }
105491041Sobrien	}
105591041Sobrien      internal_a.o_maxstack = xcoff_data (abfd)->maxstack;
105691041Sobrien      internal_a.o_maxdata = xcoff_data (abfd)->maxdata;
105791041Sobrien    }
105891041Sobrien
105991041Sobrien  if (bfd_seek (abfd, (file_ptr) 0, 0) != 0)
1060130561Sobrien    return FALSE;
106191041Sobrien
106291041Sobrien  {
106391041Sobrien    char * buff;
106491041Sobrien    bfd_size_type amount = bfd_coff_filhsz (abfd);
106591041Sobrien
106691041Sobrien    buff = bfd_malloc (amount);
106791041Sobrien    if (buff == NULL)
1068130561Sobrien      return FALSE;
106991041Sobrien
107091041Sobrien    bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, (PTR) buff);
107191041Sobrien    amount = bfd_bwrite ((PTR) buff, amount, abfd);
107291041Sobrien
107391041Sobrien    free (buff);
107491041Sobrien
107591041Sobrien    if (amount != bfd_coff_filhsz (abfd))
1076130561Sobrien      return FALSE;
107791041Sobrien  }
107891041Sobrien
107991041Sobrien  if (abfd->flags & EXEC_P)
108091041Sobrien    {
108191041Sobrien      char * buff;
108291041Sobrien      bfd_size_type amount = bfd_coff_aoutsz (abfd);
108391041Sobrien
108491041Sobrien      buff = bfd_malloc (amount);
108591041Sobrien      if (buff == NULL)
1086130561Sobrien	return FALSE;
108791041Sobrien
1088130561Sobrien      bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, (PTR) buff);
108991041Sobrien      amount = bfd_bwrite ((PTR) buff, amount, abfd);
109091041Sobrien
109191041Sobrien      free (buff);
109291041Sobrien
109391041Sobrien      if (amount != bfd_coff_aoutsz (abfd))
1094130561Sobrien	return FALSE;
109591041Sobrien    }
109691041Sobrien
1097130561Sobrien  return TRUE;
109891041Sobrien}
109991041Sobrien
1100130561Sobrienstatic bfd_boolean
1101130561Sobrienxcoff64_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
1102104834Sobrien		       val, addend, relocation, contents)
1103104834Sobrien     bfd *input_bfd;
1104104834Sobrien     asection *input_section;
1105104834Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
1106104834Sobrien     struct internal_reloc *rel;
1107104834Sobrien     struct internal_syment *sym ATTRIBUTE_UNUSED;
1108104834Sobrien     struct reloc_howto_struct *howto;
1109104834Sobrien     bfd_vma val;
1110104834Sobrien     bfd_vma addend;
1111104834Sobrien     bfd_vma *relocation;
1112104834Sobrien     bfd_byte *contents;
1113104834Sobrien{
1114104834Sobrien  struct xcoff_link_hash_entry *h;
111591041Sobrien
1116130561Sobrien  if (0 > rel->r_symndx)
1117130561Sobrien    return FALSE;
1118104834Sobrien
1119104834Sobrien  h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
1120104834Sobrien
1121104834Sobrien  /* If we see an R_BR or R_RBR reloc which is jumping to global
1122104834Sobrien     linkage code, and it is followed by an appropriate cror nop
1123104834Sobrien     instruction, we replace the cror with ld r2,40(r1).  This
1124104834Sobrien     restores the TOC after the glink code.  Contrariwise, if the
1125104834Sobrien     call is followed by a ld r2,40(r1), but the call is not
1126104834Sobrien     going to global linkage code, we can replace the load with a
1127104834Sobrien     cror.  */
1128130561Sobrien  if (NULL != h
1129130561Sobrien      && bfd_link_hash_defined == h->root.type
1130218822Sdim      && rel->r_vaddr - input_section->vma + 8 <= input_section->size)
1131104834Sobrien    {
1132104834Sobrien      bfd_byte *pnext;
1133104834Sobrien      unsigned long next;
1134130561Sobrien
1135104834Sobrien      pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
1136104834Sobrien      next = bfd_get_32 (input_bfd, pnext);
1137130561Sobrien
1138130561Sobrien      /* The _ptrgl function is magic.  It is used by the AIX compiler to call
1139104834Sobrien	 a function through a pointer.  */
1140130561Sobrien      if (h->smclas == XMC_GL || strcmp (h->root.root.string, "._ptrgl") == 0)
1141104834Sobrien	{
1142130561Sobrien	  if (next == 0x4def7b82			/* cror 15,15,15  */
1143130561Sobrien	      || next == 0x4ffffb82			/* cror 31,31,31  */
1144130561Sobrien	      || next == 0x60000000)			/* ori	r0,r0,0	  */
1145130561Sobrien	    bfd_put_32 (input_bfd, 0xe8410028, pnext);	/* ld	r2,40(r1) */
1146130561Sobrien	}
1147130561Sobrien      else
1148104834Sobrien	{
1149130561Sobrien	  if (next == 0xe8410028)			/* ld r2,40(r1)	  */
1150130561Sobrien	    bfd_put_32 (input_bfd, 0x60000000, pnext);	/* ori r0,r0,0	  */
1151104834Sobrien	}
1152130561Sobrien    }
1153130561Sobrien  else if (NULL != h && bfd_link_hash_undefined == h->root.type)
1154104834Sobrien    {
1155104834Sobrien      /* Normally, this relocation is against a defined symbol.  In the
1156104834Sobrien	 case where this is a partial link and the output section offset
1157130561Sobrien	 is greater than 2^25, the linker will return an invalid error
1158104834Sobrien	 message that the relocation has been truncated.  Yes it has been
1159130561Sobrien	 truncated but no it not important.  For this case, disable the
1160104834Sobrien	 overflow checking. */
1161104834Sobrien      howto->complain_on_overflow = complain_overflow_dont;
1162104834Sobrien    }
1163130561Sobrien
1164130561Sobrien  howto->pc_relative = TRUE;
1165104834Sobrien  howto->src_mask &= ~3;
1166104834Sobrien  howto->dst_mask = howto->src_mask;
1167130561Sobrien
1168104834Sobrien  /* A PC relative reloc includes the section address.  */
1169104834Sobrien  addend += input_section->vma;
1170130561Sobrien
1171104834Sobrien  *relocation = val + addend;
1172104834Sobrien  *relocation -= (input_section->output_section->vma
1173104834Sobrien		  + input_section->output_offset);
1174130561Sobrien  return TRUE;
1175104834Sobrien}
1176104834Sobrien
1177104834Sobrien/* This is the relocation function for the PowerPC64.
1178104834Sobrien   See xcoff_ppc_relocation_section for more information. */
1179104834Sobrien
1180130561Sobrienbfd_boolean
118191041Sobrienxcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
118291041Sobrien			      input_section, contents, relocs, syms,
118391041Sobrien			      sections)
118491041Sobrien     bfd *output_bfd;
118591041Sobrien     struct bfd_link_info *info;
118691041Sobrien     bfd *input_bfd;
118791041Sobrien     asection *input_section;
118891041Sobrien     bfd_byte *contents;
118991041Sobrien     struct internal_reloc *relocs;
119091041Sobrien     struct internal_syment *syms;
119191041Sobrien     asection **sections;
119291041Sobrien{
119391041Sobrien  struct internal_reloc *rel;
119491041Sobrien  struct internal_reloc *relend;
119591041Sobrien
119691041Sobrien  rel = relocs;
119791041Sobrien  relend = rel + input_section->reloc_count;
119891041Sobrien  for (; rel < relend; rel++)
119991041Sobrien    {
120091041Sobrien      long symndx;
120191041Sobrien      struct xcoff_link_hash_entry *h;
120291041Sobrien      struct internal_syment *sym;
120391041Sobrien      bfd_vma addend;
120491041Sobrien      bfd_vma val;
120591041Sobrien      struct reloc_howto_struct howto;
1206104834Sobrien      bfd_vma relocation;
1207104834Sobrien      bfd_vma value_to_relocate;
1208104834Sobrien      bfd_vma address;
1209104834Sobrien      bfd_byte *location;
121091041Sobrien
121191041Sobrien      /* Relocation type R_REF is a special relocation type which is
1212130561Sobrien	 merely used to prevent garbage collection from occurring for
1213130561Sobrien	 the csect including the symbol which it references.  */
121491041Sobrien      if (rel->r_type == R_REF)
121591041Sobrien	continue;
121691041Sobrien
1217104834Sobrien      /* howto */
121891041Sobrien      howto.type = rel->r_type;
121991041Sobrien      howto.rightshift = 0;
122091041Sobrien      howto.bitsize = (rel->r_size & 0x3f) + 1;
1221104834Sobrien      howto.size = howto.bitsize > 16 ? (howto.bitsize > 32 ? 4 : 2) : 1;
1222130561Sobrien      howto.pc_relative = FALSE;
122391041Sobrien      howto.bitpos = 0;
1224104834Sobrien      howto.complain_on_overflow = (rel->r_size & 0x80
1225104834Sobrien				    ? complain_overflow_signed
1226104834Sobrien				    : complain_overflow_bitfield);
122791041Sobrien      howto.special_function = NULL;
122891041Sobrien      howto.name = "internal";
1229130561Sobrien      howto.partial_inplace = TRUE;
1230130561Sobrien      howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
1231130561Sobrien      howto.pcrel_offset = FALSE;
123291041Sobrien
1233104834Sobrien      /* symbol */
123491041Sobrien      val = 0;
1235104834Sobrien      addend = 0;
1236104834Sobrien      h = NULL;
1237104834Sobrien      sym = NULL;
1238130561Sobrien      symndx = rel->r_symndx;
123991041Sobrien
1240130561Sobrien      if (-1 != symndx)
124191041Sobrien	{
124291041Sobrien	  asection *sec;
1243130561Sobrien
1244104834Sobrien	  h = obj_xcoff_sym_hashes (input_bfd)[symndx];
1245104834Sobrien	  sym = syms + symndx;
1246104834Sobrien	  addend = - sym->n_value;
1247130561Sobrien
1248130561Sobrien	  if (NULL == h)
124991041Sobrien	    {
125091041Sobrien	      sec = sections[symndx];
125191041Sobrien	      /* Hack to make sure we use the right TOC anchor value
125291041Sobrien		 if this reloc is against the TOC anchor.  */
125391041Sobrien	      if (sec->name[3] == '0'
125491041Sobrien		  && strcmp (sec->name, ".tc0") == 0)
125591041Sobrien		val = xcoff_data (output_bfd)->toc;
125691041Sobrien	      else
125791041Sobrien		val = (sec->output_section->vma
125891041Sobrien		       + sec->output_offset
125991041Sobrien		       + sym->n_value
126091041Sobrien		       - sec->vma);
1261130561Sobrien	    }
1262130561Sobrien	  else
126391041Sobrien	    {
1264130561Sobrien	      if (h->root.type == bfd_link_hash_defined
1265130561Sobrien		  || h->root.type == bfd_link_hash_defweak)
126691041Sobrien		{
1267104834Sobrien		  sec = h->root.u.def.section;
1268104834Sobrien		  val = (h->root.u.def.value
1269104834Sobrien			 + sec->output_section->vma
1270104834Sobrien			 + sec->output_offset);
1271130561Sobrien		}
1272130561Sobrien	      else if (h->root.type == bfd_link_hash_common)
1273104834Sobrien		{
1274104834Sobrien		  sec = h->root.u.c.p->section;
1275104834Sobrien		  val = (sec->output_section->vma
1276104834Sobrien			 + sec->output_offset);
1277130561Sobrien		}
1278130561Sobrien	      else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
1279130561Sobrien		       && ! info->relocatable)
1280104834Sobrien		{
1281104834Sobrien		  if (! ((*info->callbacks->undefined_symbol)
1282104834Sobrien			 (info, h->root.root.string, input_bfd, input_section,
1283130561Sobrien			  rel->r_vaddr - input_section->vma, TRUE)))
1284130561Sobrien		    return FALSE;
1285130561Sobrien
1286104834Sobrien		  /* Don't try to process the reloc.  It can't help, and
1287104834Sobrien		     it may generate another error.  */
1288104834Sobrien		  continue;
128991041Sobrien		}
129091041Sobrien	    }
129191041Sobrien	}
1292130561Sobrien
1293130561Sobrien      if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
1294130561Sobrien	  || !((*xcoff64_calculate_relocation[rel->r_type])
1295130561Sobrien	      (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
1296130561Sobrien	       addend, &relocation, contents)))
1297130561Sobrien	return FALSE;
1298130561Sobrien
1299104834Sobrien      /* address */
1300104834Sobrien      address = rel->r_vaddr - input_section->vma;
1301104834Sobrien      location = contents + address;
1302130561Sobrien
1303218822Sdim      if (address > input_section->size)
1304130561Sobrien	abort ();
1305130561Sobrien
1306104834Sobrien      /* Get the value we are going to relocate.  */
1307104834Sobrien      if (1 == howto.size)
1308104834Sobrien	value_to_relocate = bfd_get_16 (input_bfd, location);
1309104834Sobrien      else if (2 == howto.size)
1310104834Sobrien	value_to_relocate = bfd_get_32 (input_bfd, location);
1311130561Sobrien      else
1312104834Sobrien	value_to_relocate = bfd_get_64 (input_bfd, location);
1313130561Sobrien
1314130561Sobrien      /* overflow.
1315130561Sobrien
1316104834Sobrien	 FIXME: We may drop bits during the addition
1317104834Sobrien	 which we don't check for.  We must either check at every single
1318104834Sobrien	 operation, which would be tedious, or we must do the computations
1319104834Sobrien	 in a type larger than bfd_vma, which would be inefficient.  */
1320130561Sobrien
1321104834Sobrien      if ((unsigned int) howto.complain_on_overflow
1322104834Sobrien	  >= XCOFF_MAX_COMPLAIN_OVERFLOW)
1323130561Sobrien	abort ();
1324130561Sobrien
1325104834Sobrien      if (((*xcoff_complain_overflow[howto.complain_on_overflow])
1326130561Sobrien	   (input_bfd, value_to_relocate, relocation, &howto)))
132791041Sobrien	{
1328104834Sobrien	  const char *name;
1329104834Sobrien	  char buf[SYMNMLEN + 1];
1330104834Sobrien	  char reloc_type_name[10];
1331130561Sobrien
1332130561Sobrien	  if (symndx == -1)
133391041Sobrien	    {
1334104834Sobrien	      name = "*ABS*";
1335130561Sobrien	    }
1336130561Sobrien	  else if (h != NULL)
133791041Sobrien	    {
1338218822Sdim	      name = NULL;
1339130561Sobrien	    }
1340130561Sobrien	  else
1341104834Sobrien	    {
1342104834Sobrien	      name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
1343104834Sobrien	      if (name == NULL)
1344104834Sobrien		name = "UNKNOWN";
134591041Sobrien	    }
1346104834Sobrien	  sprintf (reloc_type_name, "0x%02x", rel->r_type);
1347130561Sobrien
1348104834Sobrien	  if (! ((*info->callbacks->reloc_overflow)
1349218822Sdim		 (info, (h ? &h->root : NULL), name, reloc_type_name,
1350218822Sdim		  (bfd_vma) 0, input_bfd, input_section,
1351218822Sdim		  rel->r_vaddr - input_section->vma)))
1352130561Sobrien	    return FALSE;
135391041Sobrien	}
135491041Sobrien
1355104834Sobrien      /* Add RELOCATION to the right bits of VALUE_TO_RELOCATE.  */
1356104834Sobrien      value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
1357104834Sobrien			   | (((value_to_relocate & howto.src_mask)
1358104834Sobrien			       + relocation) & howto.dst_mask));
1359130561Sobrien
1360104834Sobrien      /* Put the value back in the object file.  */
1361104834Sobrien      if (1 == howto.size)
1362104834Sobrien	bfd_put_16 (input_bfd, value_to_relocate, location);
1363104834Sobrien      else if (2 == howto.size)
1364104834Sobrien	bfd_put_32 (input_bfd, value_to_relocate, location);
1365104834Sobrien      else
1366104834Sobrien	bfd_put_64 (input_bfd, value_to_relocate, location);
1367130561Sobrien
136891041Sobrien    }
1369130561Sobrien  return TRUE;
137091041Sobrien}
137191041Sobrien
137291041Sobrien
137391041Sobrien/* The XCOFF reloc table.  Actually, XCOFF relocations specify the
137491041Sobrien   bitsize and whether they are signed or not, along with a
137591041Sobrien   conventional type.  This table is for the types, which are used for
137691041Sobrien   different algorithms for putting in the reloc.  Many of these
137791041Sobrien   relocs need special_function entries, which I have not written.  */
137891041Sobrien
137991041Sobrienreloc_howto_type xcoff64_howto_table[] =
138091041Sobrien{
138191041Sobrien  /* Standard 64 bit relocation.  */
1382104834Sobrien  HOWTO (R_POS,			/* type */
138391041Sobrien	 0,			/* rightshift */
138491041Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
138591041Sobrien	 64,			/* bitsize */
1386130561Sobrien	 FALSE,			/* pc_relative */
138791041Sobrien	 0,			/* bitpos */
138891041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
138991041Sobrien	 0,			/* special_function */
1390104834Sobrien	 "R_POS_64",		/* name */
1391130561Sobrien	 TRUE,			/* partial_inplace */
139291041Sobrien	 MINUS_ONE,		/* src_mask */
139391041Sobrien	 MINUS_ONE,		/* dst_mask */
1394130561Sobrien	 FALSE),		/* pcrel_offset */
139591041Sobrien
139691041Sobrien  /* 64 bit relocation, but store negative value.  */
1397104834Sobrien  HOWTO (R_NEG,			/* type */
139891041Sobrien	 0,			/* rightshift */
139991041Sobrien	 -4,			/* size (0 = byte, 1 = short, 2 = long) */
140091041Sobrien	 64,			/* bitsize */
1401130561Sobrien	 FALSE,			/* pc_relative */
140291041Sobrien	 0,			/* bitpos */
140391041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
140491041Sobrien	 0,			/* special_function */
140591041Sobrien	 "R_NEG",		/* name */
1406130561Sobrien	 TRUE,			/* partial_inplace */
140791041Sobrien	 MINUS_ONE,		/* src_mask */
140891041Sobrien	 MINUS_ONE,		/* dst_mask */
1409130561Sobrien	 FALSE),		/* pcrel_offset */
141091041Sobrien
141191041Sobrien  /* 32 bit PC relative relocation.  */
1412104834Sobrien  HOWTO (R_REL,			/* type */
141391041Sobrien	 0,			/* rightshift */
141491041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
141591041Sobrien	 32,			/* bitsize */
1416130561Sobrien	 TRUE,			/* pc_relative */
141791041Sobrien	 0,			/* bitpos */
141891041Sobrien	 complain_overflow_signed, /* complain_on_overflow */
141991041Sobrien	 0,			/* special_function */
142091041Sobrien	 "R_REL",		/* name */
1421130561Sobrien	 TRUE,			/* partial_inplace */
142291041Sobrien	 0xffffffff,		/* src_mask */
142391041Sobrien	 0xffffffff,		/* dst_mask */
1424130561Sobrien	 FALSE),		/* pcrel_offset */
142591041Sobrien
142691041Sobrien  /* 16 bit TOC relative relocation.  */
1427104834Sobrien  HOWTO (R_TOC,			/* type */
142891041Sobrien	 0,			/* rightshift */
142991041Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
143091041Sobrien	 16,			/* bitsize */
1431130561Sobrien	 FALSE,			/* pc_relative */
143291041Sobrien	 0,			/* bitpos */
143391041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
143491041Sobrien	 0,			/* special_function */
143591041Sobrien	 "R_TOC",		/* name */
1436130561Sobrien	 TRUE,			/* partial_inplace */
143791041Sobrien	 0xffff,		/* src_mask */
143891041Sobrien	 0xffff,		/* dst_mask */
1439130561Sobrien	 FALSE),		/* pcrel_offset */
144091041Sobrien
1441130561Sobrien  /* I don't really know what this is.	*/
1442104834Sobrien  HOWTO (R_RTB,			/* type */
144391041Sobrien	 1,			/* rightshift */
144491041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
144591041Sobrien	 32,			/* bitsize */
1446130561Sobrien	 FALSE,			/* pc_relative */
144791041Sobrien	 0,			/* bitpos */
144891041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
144991041Sobrien	 0,			/* special_function */
145091041Sobrien	 "R_RTB",		/* name */
1451130561Sobrien	 TRUE,			/* partial_inplace */
145291041Sobrien	 0xffffffff,		/* src_mask */
145391041Sobrien	 0xffffffff,		/* dst_mask */
1454130561Sobrien	 FALSE),		/* pcrel_offset */
145591041Sobrien
145691041Sobrien  /* External TOC relative symbol.  */
1457104834Sobrien  HOWTO (R_GL,			/* type */
145891041Sobrien	 0,			/* rightshift */
1459104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
146091041Sobrien	 16,			/* bitsize */
1461130561Sobrien	 FALSE,			/* pc_relative */
146291041Sobrien	 0,			/* bitpos */
146391041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
146491041Sobrien	 0,			/* special_function */
146591041Sobrien	 "R_GL",		/* name */
1466130561Sobrien	 TRUE,			/* partial_inplace */
146791041Sobrien	 0xffff,		/* src_mask */
146891041Sobrien	 0xffff,		/* dst_mask */
1469130561Sobrien	 FALSE),		/* pcrel_offset */
147091041Sobrien
147191041Sobrien  /* Local TOC relative symbol.	 */
1472104834Sobrien  HOWTO (R_TCL,			/* type */
147391041Sobrien	 0,			/* rightshift */
1474104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
147591041Sobrien	 16,			/* bitsize */
1476130561Sobrien	 FALSE,			/* pc_relative */
147791041Sobrien	 0,			/* bitpos */
147891041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
147991041Sobrien	 0,			/* special_function */
148091041Sobrien	 "R_TCL",		/* name */
1481130561Sobrien	 TRUE,			/* partial_inplace */
148291041Sobrien	 0xffff,		/* src_mask */
148391041Sobrien	 0xffff,		/* dst_mask */
1484130561Sobrien	 FALSE),		/* pcrel_offset */
148591041Sobrien
148691041Sobrien  EMPTY_HOWTO (7),
148791041Sobrien
148891041Sobrien  /* Non modifiable absolute branch.  */
1489104834Sobrien  HOWTO (R_BA,			/* type */
149091041Sobrien	 0,			/* rightshift */
149191041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
149291041Sobrien	 26,			/* bitsize */
1493130561Sobrien	 FALSE,			/* pc_relative */
149491041Sobrien	 0,			/* bitpos */
149591041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
149691041Sobrien	 0,			/* special_function */
1497104834Sobrien	 "R_BA_26",		/* name */
1498130561Sobrien	 TRUE,			/* partial_inplace */
1499130561Sobrien	 0x03fffffc,		/* src_mask */
1500130561Sobrien	 0x03fffffc,		/* dst_mask */
1501130561Sobrien	 FALSE),		/* pcrel_offset */
150291041Sobrien
150391041Sobrien  EMPTY_HOWTO (9),
150491041Sobrien
150591041Sobrien  /* Non modifiable relative branch.  */
1506104834Sobrien  HOWTO (R_BR,			/* type */
150791041Sobrien	 0,			/* rightshift */
150891041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
150991041Sobrien	 26,			/* bitsize */
1510130561Sobrien	 TRUE,			/* pc_relative */
151191041Sobrien	 0,			/* bitpos */
151291041Sobrien	 complain_overflow_signed, /* complain_on_overflow */
151391041Sobrien	 0,			/* special_function */
151491041Sobrien	 "R_BR",		/* name */
1515130561Sobrien	 TRUE,			/* partial_inplace */
1516130561Sobrien	 0x03fffffc,		/* src_mask */
1517130561Sobrien	 0x03fffffc,		/* dst_mask */
1518130561Sobrien	 FALSE),		/* pcrel_offset */
151991041Sobrien
152091041Sobrien  EMPTY_HOWTO (0xb),
152191041Sobrien
152291041Sobrien  /* Indirect load.  */
1523104834Sobrien  HOWTO (R_RL,			/* type */
152491041Sobrien	 0,			/* rightshift */
1525104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
152691041Sobrien	 16,			/* bitsize */
1527130561Sobrien	 FALSE,			/* pc_relative */
152891041Sobrien	 0,			/* bitpos */
152991041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
153091041Sobrien	 0,			/* special_function */
153191041Sobrien	 "R_RL",		/* name */
1532130561Sobrien	 TRUE,			/* partial_inplace */
153391041Sobrien	 0xffff,		/* src_mask */
153491041Sobrien	 0xffff,		/* dst_mask */
1535130561Sobrien	 FALSE),		/* pcrel_offset */
153691041Sobrien
153791041Sobrien  /* Load address.  */
1538104834Sobrien  HOWTO (R_RLA,			/* type */
153991041Sobrien	 0,			/* rightshift */
1540104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
154191041Sobrien	 16,			/* bitsize */
1542130561Sobrien	 FALSE,			/* pc_relative */
154391041Sobrien	 0,			/* bitpos */
154491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
154591041Sobrien	 0,			/* special_function */
154691041Sobrien	 "R_RLA",		/* name */
1547130561Sobrien	 TRUE,			/* partial_inplace */
154891041Sobrien	 0xffff,		/* src_mask */
154991041Sobrien	 0xffff,		/* dst_mask */
1550130561Sobrien	 FALSE),		/* pcrel_offset */
155191041Sobrien
155291041Sobrien  EMPTY_HOWTO (0xe),
155391041Sobrien
1554130561Sobrien  /* Non-relocating reference.	*/
1555104834Sobrien  HOWTO (R_REF,			/* type */
155691041Sobrien	 0,			/* rightshift */
155791041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
155891041Sobrien	 32,			/* bitsize */
1559130561Sobrien	 FALSE,			/* pc_relative */
156091041Sobrien	 0,			/* bitpos */
1561104834Sobrien	 complain_overflow_dont, /* complain_on_overflow */
156291041Sobrien	 0,			/* special_function */
156391041Sobrien	 "R_REF",		/* name */
1564130561Sobrien	 FALSE,			/* partial_inplace */
156591041Sobrien	 0,			/* src_mask */
156691041Sobrien	 0,			/* dst_mask */
1567130561Sobrien	 FALSE),		/* pcrel_offset */
156891041Sobrien
156991041Sobrien  EMPTY_HOWTO (0x10),
157091041Sobrien  EMPTY_HOWTO (0x11),
157191041Sobrien
157291041Sobrien  /* TOC relative indirect load.  */
1573104834Sobrien  HOWTO (R_TRL,			/* type */
157491041Sobrien	 0,			/* rightshift */
1575104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
157691041Sobrien	 16,			/* bitsize */
1577130561Sobrien	 FALSE,			/* pc_relative */
157891041Sobrien	 0,			/* bitpos */
157991041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
158091041Sobrien	 0,			/* special_function */
158191041Sobrien	 "R_TRL",		/* name */
1582130561Sobrien	 TRUE,			/* partial_inplace */
158391041Sobrien	 0xffff,		/* src_mask */
158491041Sobrien	 0xffff,		/* dst_mask */
1585130561Sobrien	 FALSE),		/* pcrel_offset */
158691041Sobrien
158791041Sobrien  /* TOC relative load address.	 */
1588104834Sobrien  HOWTO (R_TRLA,		/* type */
158991041Sobrien	 0,			/* rightshift */
1590104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
159191041Sobrien	 16,			/* bitsize */
1592130561Sobrien	 FALSE,			/* pc_relative */
159391041Sobrien	 0,			/* bitpos */
159491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
159591041Sobrien	 0,			/* special_function */
159691041Sobrien	 "R_TRLA",		/* name */
1597130561Sobrien	 TRUE,			/* partial_inplace */
159891041Sobrien	 0xffff,		/* src_mask */
159991041Sobrien	 0xffff,		/* dst_mask */
1600130561Sobrien	 FALSE),		/* pcrel_offset */
160191041Sobrien
160291041Sobrien  /* Modifiable relative branch.  */
1603104834Sobrien  HOWTO (R_RRTBI,		/* type */
160491041Sobrien	 1,			/* rightshift */
160591041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
160691041Sobrien	 32,			/* bitsize */
1607130561Sobrien	 FALSE,			/* pc_relative */
160891041Sobrien	 0,			/* bitpos */
160991041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
161091041Sobrien	 0,			/* special_function */
161191041Sobrien	 "R_RRTBI",		/* name */
1612130561Sobrien	 TRUE,			/* partial_inplace */
161391041Sobrien	 0xffffffff,		/* src_mask */
161491041Sobrien	 0xffffffff,		/* dst_mask */
1615130561Sobrien	 FALSE),		/* pcrel_offset */
161691041Sobrien
161791041Sobrien  /* Modifiable absolute branch.  */
1618104834Sobrien  HOWTO (R_RRTBA,		/* type */
161991041Sobrien	 1,			/* rightshift */
162091041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
162191041Sobrien	 32,			/* bitsize */
1622130561Sobrien	 FALSE,			/* pc_relative */
162391041Sobrien	 0,			/* bitpos */
162491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
162591041Sobrien	 0,			/* special_function */
162691041Sobrien	 "R_RRTBA",		/* name */
1627130561Sobrien	 TRUE,			/* partial_inplace */
162891041Sobrien	 0xffffffff,		/* src_mask */
162991041Sobrien	 0xffffffff,		/* dst_mask */
1630130561Sobrien	 FALSE),		/* pcrel_offset */
163191041Sobrien
163291041Sobrien  /* Modifiable call absolute indirect.	 */
1633104834Sobrien  HOWTO (R_CAI,			/* type */
163491041Sobrien	 0,			/* rightshift */
1635104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
163691041Sobrien	 16,			/* bitsize */
1637130561Sobrien	 FALSE,			/* pc_relative */
163891041Sobrien	 0,			/* bitpos */
163991041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
164091041Sobrien	 0,			/* special_function */
164191041Sobrien	 "R_CAI",		/* name */
1642130561Sobrien	 TRUE,			/* partial_inplace */
164391041Sobrien	 0xffff,		/* src_mask */
164491041Sobrien	 0xffff,		/* dst_mask */
1645130561Sobrien	 FALSE),		/* pcrel_offset */
164691041Sobrien
1647130561Sobrien  /* Modifiable call relative.	*/
1648104834Sobrien  HOWTO (R_CREL,		/* type */
164991041Sobrien	 0,			/* rightshift */
1650104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
165191041Sobrien	 16,			/* bitsize */
1652130561Sobrien	 FALSE,			/* pc_relative */
165391041Sobrien	 0,			/* bitpos */
165491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
165591041Sobrien	 0,			/* special_function */
165691041Sobrien	 "R_CREL",		/* name */
1657130561Sobrien	 TRUE,			/* partial_inplace */
165891041Sobrien	 0xffff,		/* src_mask */
165991041Sobrien	 0xffff,		/* dst_mask */
1660130561Sobrien	 FALSE),		/* pcrel_offset */
166191041Sobrien
166291041Sobrien  /* Modifiable branch absolute.  */
1663104834Sobrien  HOWTO (R_RBA,			/* type */
166491041Sobrien	 0,			/* rightshift */
166591041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
166691041Sobrien	 26,			/* bitsize */
1667130561Sobrien	 FALSE,			/* pc_relative */
166891041Sobrien	 0,			/* bitpos */
166991041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
167091041Sobrien	 0,			/* special_function */
167191041Sobrien	 "R_RBA",		/* name */
1672130561Sobrien	 TRUE,			/* partial_inplace */
1673104834Sobrien	 0x03fffffc,		/* src_mask */
1674104834Sobrien	 0x03fffffc,		/* dst_mask */
1675130561Sobrien	 FALSE),		/* pcrel_offset */
167691041Sobrien
167791041Sobrien  /* Modifiable branch absolute.  */
1678104834Sobrien  HOWTO (R_RBAC,		/* type */
167991041Sobrien	 0,			/* rightshift */
168091041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
168191041Sobrien	 32,			/* bitsize */
1682130561Sobrien	 FALSE,			/* pc_relative */
168391041Sobrien	 0,			/* bitpos */
168491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
168591041Sobrien	 0,			/* special_function */
168691041Sobrien	 "R_RBAC",		/* name */
1687130561Sobrien	 TRUE,			/* partial_inplace */
1688104834Sobrien	 0xffffffff,		/* src_mask */
1689104834Sobrien	 0xffffffff,		/* dst_mask */
1690130561Sobrien	 FALSE),		/* pcrel_offset */
169191041Sobrien
169291041Sobrien  /* Modifiable branch relative.  */
1693104834Sobrien  HOWTO (R_RBR,			/* type */
169491041Sobrien	 0,			/* rightshift */
169591041Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
169691041Sobrien	 26,			/* bitsize */
1697130561Sobrien	 FALSE,			/* pc_relative */
169891041Sobrien	 0,			/* bitpos */
169991041Sobrien	 complain_overflow_signed, /* complain_on_overflow */
170091041Sobrien	 0,			/* special_function */
1701104834Sobrien	 "R_RBR_26",		/* name */
1702130561Sobrien	 TRUE,			/* partial_inplace */
1703104834Sobrien	 0x03fffffc,		/* src_mask */
1704104834Sobrien	 0x03fffffc,		/* dst_mask */
1705130561Sobrien	 FALSE),		/* pcrel_offset */
170691041Sobrien
170791041Sobrien  /* Modifiable branch absolute.  */
1708104834Sobrien  HOWTO (R_RBRC,		/* type */
170991041Sobrien	 0,			/* rightshift */
1710104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
171191041Sobrien	 16,			/* bitsize */
1712130561Sobrien	 FALSE,			/* pc_relative */
171391041Sobrien	 0,			/* bitpos */
171491041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
171591041Sobrien	 0,			/* special_function */
171691041Sobrien	 "R_RBRC",		/* name */
1717130561Sobrien	 TRUE,			/* partial_inplace */
171891041Sobrien	 0xffff,		/* src_mask */
171991041Sobrien	 0xffff,		/* dst_mask */
1720130561Sobrien	 FALSE),		/* pcrel_offset */
172191041Sobrien
1722104834Sobrien  HOWTO (R_POS,			/* type */
172391041Sobrien	 0,			/* rightshift */
1724104834Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1725104834Sobrien	 32,			/* bitsize */
1726130561Sobrien	 FALSE,			/* pc_relative */
172791041Sobrien	 0,			/* bitpos */
172891041Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
172991041Sobrien	 0,			/* special_function */
1730104834Sobrien	 "R_POS_32",		/* name */
1731130561Sobrien	 TRUE,			/* partial_inplace */
1732104834Sobrien	 0xffffffff,		/* src_mask */
1733104834Sobrien	 0xffffffff,		/* dst_mask */
1734130561Sobrien	 FALSE),		/* pcrel_offset */
1735104834Sobrien
1736104834Sobrien  /* 16 bit Non modifiable absolute branch.  */
1737104834Sobrien  HOWTO (R_BA,			/* type */
1738104834Sobrien	 0,			/* rightshift */
1739104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1740104834Sobrien	 16,			/* bitsize */
1741130561Sobrien	 FALSE,			/* pc_relative */
1742104834Sobrien	 0,			/* bitpos */
1743104834Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
1744104834Sobrien	 0,			/* special_function */
1745104834Sobrien	 "R_BA_16",		/* name */
1746130561Sobrien	 TRUE,			/* partial_inplace */
1747104834Sobrien	 0xfffc,		/* src_mask */
1748104834Sobrien	 0xfffc,		/* dst_mask */
1749130561Sobrien	 FALSE),		/* pcrel_offset */
1750104834Sobrien
1751104834Sobrien  /* Modifiable branch relative.  */
1752130561Sobrien  HOWTO (R_RBR,			/* type */
1753130561Sobrien	 0,			/* rightshift */
1754130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1755130561Sobrien	 16,			/* bitsize */
1756130561Sobrien	 FALSE,			/* pc_relative */
1757130561Sobrien	 0,			/* bitpos */
1758104834Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1759130561Sobrien	 0,			/* special_function */
1760130561Sobrien	 "R_RBR_16",		/* name */
1761130561Sobrien	 TRUE,			/* partial_inplace */
1762130561Sobrien	 0xffff,		/* src_mask */
1763130561Sobrien	 0xffff,		/* dst_mask */
1764130561Sobrien	 FALSE),		/* pcrel_offset */
1765104834Sobrien
1766104834Sobrien  /* Modifiable branch absolute.  */
1767104834Sobrien  HOWTO (R_RBA,			/* type */
1768104834Sobrien	 0,			/* rightshift */
1769104834Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1770104834Sobrien	 16,			/* bitsize */
1771130561Sobrien	 FALSE,			/* pc_relative */
1772104834Sobrien	 0,			/* bitpos */
1773104834Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
1774104834Sobrien	 0,			/* special_function */
1775104834Sobrien	 "R_RBA_16",		/* name */
1776130561Sobrien	 TRUE,			/* partial_inplace */
1777104834Sobrien	 0xffff,		/* src_mask */
1778104834Sobrien	 0xffff,		/* dst_mask */
1779130561Sobrien	 FALSE),		/* pcrel_offset */
1780104834Sobrien
178191041Sobrien};
178291041Sobrien
178391041Sobrienvoid
178491041Sobrienxcoff64_rtype2howto (relent, internal)
178591041Sobrien     arelent *relent;
178691041Sobrien     struct internal_reloc *internal;
178791041Sobrien{
1788104834Sobrien  if (internal->r_type > R_RBRC)
178991041Sobrien    abort ();
179091041Sobrien
1791104834Sobrien  /* Default howto layout works most of the time */
1792104834Sobrien  relent->howto = &xcoff64_howto_table[internal->r_type];
1793130561Sobrien
1794130561Sobrien  /* Special case some 16 bit reloc */
1795104834Sobrien  if (15 == (internal->r_size & 0x3f))
1796104834Sobrien    {
1797130561Sobrien      if (R_BA == internal->r_type)
1798104834Sobrien	relent->howto = &xcoff64_howto_table[0x1d];
1799130561Sobrien      else if (R_RBR == internal->r_type)
1800104834Sobrien	relent->howto = &xcoff64_howto_table[0x1e];
1801130561Sobrien      else if (R_RBA == internal->r_type)
1802104834Sobrien	relent->howto = &xcoff64_howto_table[0x1f];
1803104834Sobrien    }
1804104834Sobrien  /* Special case 32 bit */
1805104834Sobrien  else if (31 == (internal->r_size & 0x3f))
1806104834Sobrien    {
1807130561Sobrien      if (R_POS == internal->r_type)
1808104834Sobrien	relent->howto = &xcoff64_howto_table[0x1c];
1809104834Sobrien    }
1810130561Sobrien
181191041Sobrien  /* The r_size field of an XCOFF reloc encodes the bitsize of the
181291041Sobrien     relocation, as well as indicating whether it is signed or not.
181391041Sobrien     Doublecheck that the relocation information gathered from the
181491041Sobrien     type matches this information.  The bitsize is not significant
181591041Sobrien     for R_REF relocs.  */
181691041Sobrien  if (relent->howto->dst_mask != 0
181791041Sobrien      && (relent->howto->bitsize
181891041Sobrien	  != ((unsigned int) internal->r_size & 0x3f) + 1))
181991041Sobrien    abort ();
182091041Sobrien}
182191041Sobrien
182291041Sobrienreloc_howto_type *
182391041Sobrienxcoff64_reloc_type_lookup (abfd, code)
182491041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
182591041Sobrien     bfd_reloc_code_real_type code;
182691041Sobrien{
182791041Sobrien  switch (code)
182891041Sobrien    {
182991041Sobrien    case BFD_RELOC_PPC_B26:
183091041Sobrien      return &xcoff64_howto_table[0xa];
1831104834Sobrien    case BFD_RELOC_PPC_BA16:
1832104834Sobrien      return &xcoff64_howto_table[0x1d];
183391041Sobrien    case BFD_RELOC_PPC_BA26:
183491041Sobrien      return &xcoff64_howto_table[8];
183591041Sobrien    case BFD_RELOC_PPC_TOC16:
183691041Sobrien      return &xcoff64_howto_table[3];
183791041Sobrien    case BFD_RELOC_32:
183891041Sobrien    case BFD_RELOC_CTOR:
1839104834Sobrien      return &xcoff64_howto_table[0x1c];
1840104834Sobrien    case BFD_RELOC_64:
184191041Sobrien      return &xcoff64_howto_table[0];
184291041Sobrien    default:
184391041Sobrien      return NULL;
184491041Sobrien    }
184591041Sobrien}
184691041Sobrien
1847218822Sdimstatic reloc_howto_type *
1848218822Sdimxcoff64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1849218822Sdim			   const char *r_name)
1850218822Sdim{
1851218822Sdim  unsigned int i;
1852218822Sdim
1853218822Sdim  for (i = 0;
1854218822Sdim       i < sizeof (xcoff64_howto_table) / sizeof (xcoff64_howto_table[0]);
1855218822Sdim       i++)
1856218822Sdim    if (xcoff64_howto_table[i].name != NULL
1857218822Sdim	&& strcasecmp (xcoff64_howto_table[i].name, r_name) == 0)
1858218822Sdim      return &xcoff64_howto_table[i];
1859218822Sdim
1860218822Sdim  return NULL;
1861218822Sdim}
1862218822Sdim
186391041Sobrien/* Read in the armap of an XCOFF archive.  */
186491041Sobrien
1865130561Sobrienstatic bfd_boolean
186691041Sobrienxcoff64_slurp_armap (abfd)
186791041Sobrien     bfd *abfd;
186891041Sobrien{
186991041Sobrien  file_ptr off;
187091041Sobrien  size_t namlen;
187191041Sobrien  bfd_size_type sz, amt;
187291041Sobrien  bfd_byte *contents, *cend;
187391041Sobrien  bfd_vma c, i;
187491041Sobrien  carsym *arsym;
187591041Sobrien  bfd_byte *p;
187691041Sobrien  file_ptr pos;
187791041Sobrien
187891041Sobrien  /* This is for the new format.  */
187991041Sobrien  struct xcoff_ar_hdr_big hdr;
188091041Sobrien
188191041Sobrien  if (xcoff_ardata (abfd) == NULL)
188291041Sobrien    {
1883130561Sobrien      bfd_has_map (abfd) = FALSE;
1884130561Sobrien      return TRUE;
188591041Sobrien    }
188691041Sobrien
1887104834Sobrien  off = bfd_scan_vma (xcoff_ardata_big (abfd)->symoff64,
1888104834Sobrien		      (const char **) NULL, 10);
188991041Sobrien  if (off == 0)
189091041Sobrien    {
1891130561Sobrien      bfd_has_map (abfd) = FALSE;
1892130561Sobrien      return TRUE;
189391041Sobrien    }
189491041Sobrien
189591041Sobrien  if (bfd_seek (abfd, off, SEEK_SET) != 0)
1896130561Sobrien    return FALSE;
189791041Sobrien
189891041Sobrien  /* The symbol table starts with a normal archive header.  */
189991041Sobrien  if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
190091041Sobrien      != SIZEOF_AR_HDR_BIG)
1901130561Sobrien    return FALSE;
190291041Sobrien
190391041Sobrien  /* Skip the name (normally empty).  */
190491041Sobrien  namlen = strtol (hdr.namlen, (char **) NULL, 10);
190591041Sobrien  pos = ((namlen + 1) & ~(size_t) 1) + SXCOFFARFMAG;
190691041Sobrien  if (bfd_seek (abfd, pos, SEEK_CUR) != 0)
1907130561Sobrien    return FALSE;
190891041Sobrien
1909104834Sobrien  sz = bfd_scan_vma (hdr.size, (const char **) NULL, 10);
191091041Sobrien
191191041Sobrien  /* Read in the entire symbol table.  */
191291041Sobrien  contents = (bfd_byte *) bfd_alloc (abfd, sz);
191391041Sobrien  if (contents == NULL)
1914130561Sobrien    return FALSE;
191591041Sobrien  if (bfd_bread ((PTR) contents, sz, abfd) != sz)
1916130561Sobrien    return FALSE;
191791041Sobrien
191891041Sobrien  /* The symbol table starts with an eight byte count.  */
191991041Sobrien  c = H_GET_64 (abfd, contents);
192091041Sobrien
192191041Sobrien  if (c * 8 >= sz)
192291041Sobrien    {
192391041Sobrien      bfd_set_error (bfd_error_bad_value);
1924130561Sobrien      return FALSE;
192591041Sobrien    }
192691041Sobrien  amt = c;
192791041Sobrien  amt *= sizeof (carsym);
192891041Sobrien  bfd_ardata (abfd)->symdefs = (carsym *) bfd_alloc (abfd, amt);
192991041Sobrien  if (bfd_ardata (abfd)->symdefs == NULL)
1930130561Sobrien    return FALSE;
193191041Sobrien
193291041Sobrien  /* After the count comes a list of eight byte file offsets.  */
193391041Sobrien  for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8;
193491041Sobrien       i < c;
193591041Sobrien       ++i, ++arsym, p += 8)
193691041Sobrien    arsym->file_offset = H_GET_64 (abfd, p);
193791041Sobrien
193891041Sobrien  /* After the file offsets come null terminated symbol names.  */
193991041Sobrien  cend = contents + sz;
194091041Sobrien  for (i = 0, arsym = bfd_ardata (abfd)->symdefs;
194191041Sobrien       i < c;
194291041Sobrien       ++i, ++arsym, p += strlen ((char *) p) + 1)
194391041Sobrien    {
194491041Sobrien      if (p >= cend)
194591041Sobrien	{
194691041Sobrien	  bfd_set_error (bfd_error_bad_value);
1947130561Sobrien	  return FALSE;
194891041Sobrien	}
194991041Sobrien      arsym->name = (char *) p;
195091041Sobrien    }
195191041Sobrien
195291041Sobrien  bfd_ardata (abfd)->symdef_count = c;
1953130561Sobrien  bfd_has_map (abfd) = TRUE;
195491041Sobrien
1955130561Sobrien  return TRUE;
195691041Sobrien}
195791041Sobrien
195891041Sobrien
195991041Sobrien/* See if this is an NEW XCOFF archive.  */
196091041Sobrien
196191041Sobrienstatic const bfd_target *
196291041Sobrienxcoff64_archive_p (abfd)
196391041Sobrien     bfd *abfd;
196491041Sobrien{
1965104834Sobrien  struct artdata *tdata_hold;
196691041Sobrien  char magic[SXCOFFARMAG];
196791041Sobrien  /* This is the new format.  */
196891041Sobrien  struct xcoff_ar_file_hdr_big hdr;
196991041Sobrien  bfd_size_type amt = SXCOFFARMAG;
197091041Sobrien
197191041Sobrien  if (bfd_bread ((PTR) magic, amt, abfd) != amt)
197291041Sobrien    {
197391041Sobrien      if (bfd_get_error () != bfd_error_system_call)
197491041Sobrien	bfd_set_error (bfd_error_wrong_format);
197591041Sobrien      return NULL;
197691041Sobrien    }
197791041Sobrien
197891041Sobrien  if (strncmp (magic, XCOFFARMAGBIG, SXCOFFARMAG) != 0)
197991041Sobrien    {
198091041Sobrien      bfd_set_error (bfd_error_wrong_format);
198191041Sobrien      return NULL;
198291041Sobrien    }
198391041Sobrien
198491041Sobrien  /* Copy over the magic string.  */
198591041Sobrien  memcpy (hdr.magic, magic, SXCOFFARMAG);
198691041Sobrien
198791041Sobrien  /* Now read the rest of the file header.  */
1988104834Sobrien  amt = SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG;
1989104834Sobrien  if (bfd_bread ((PTR) &hdr.memoff, amt, abfd) != amt)
199091041Sobrien    {
199191041Sobrien      if (bfd_get_error () != bfd_error_system_call)
199291041Sobrien	bfd_set_error (bfd_error_wrong_format);
199391041Sobrien      return NULL;
199491041Sobrien    }
199591041Sobrien
1996104834Sobrien  tdata_hold = bfd_ardata (abfd);
199791041Sobrien
1998104834Sobrien  amt = sizeof (struct artdata);
1999104834Sobrien  bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt);
2000104834Sobrien  if (bfd_ardata (abfd) == (struct artdata *) NULL)
2001104834Sobrien    goto error_ret_restore;
2002104834Sobrien
2003218822Sdim  /* Already cleared by bfd_zalloc above.
2004218822Sdim     bfd_ardata (abfd)->cache = NULL;
2005218822Sdim     bfd_ardata (abfd)->archive_head = NULL;
2006218822Sdim     bfd_ardata (abfd)->symdefs = NULL;
2007218822Sdim     bfd_ardata (abfd)->extended_names = NULL;
2008218822Sdim     bfd_ardata (abfd)->extended_names_size = 0;  */
2009104834Sobrien  bfd_ardata (abfd)->first_file_filepos = bfd_scan_vma (hdr.firstmemoff,
2010104834Sobrien							(const char **) NULL,
2011104834Sobrien							10);
2012104834Sobrien
201391041Sobrien  amt = SIZEOF_AR_FILE_HDR_BIG;
201491041Sobrien  bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt);
201591041Sobrien  if (bfd_ardata (abfd)->tdata == NULL)
2016104834Sobrien    goto error_ret;
201791041Sobrien
201891041Sobrien  memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG);
201991041Sobrien
202091041Sobrien  if (! xcoff64_slurp_armap (abfd))
202191041Sobrien    {
2022104834Sobrien    error_ret:
202391041Sobrien      bfd_release (abfd, bfd_ardata (abfd));
2024104834Sobrien    error_ret_restore:
2025104834Sobrien      bfd_ardata (abfd) = tdata_hold;
202691041Sobrien      return NULL;
202791041Sobrien    }
202891041Sobrien
202991041Sobrien  return abfd->xvec;
203091041Sobrien}
203191041Sobrien
203291041Sobrien
203391041Sobrien/* Open the next element in an XCOFF archive.  */
203491041Sobrien
203591041Sobrienstatic bfd *
203691041Sobrienxcoff64_openr_next_archived_file (archive, last_file)
203791041Sobrien     bfd *archive;
203891041Sobrien     bfd *last_file;
203991041Sobrien{
2040130561Sobrien  bfd_vma filestart;
204191041Sobrien
204291041Sobrien  if ((xcoff_ardata (archive) == NULL)
204391041Sobrien      || ! xcoff_big_format_p (archive))
204491041Sobrien    {
204591041Sobrien      bfd_set_error (bfd_error_invalid_operation);
204691041Sobrien      return NULL;
204791041Sobrien    }
204891041Sobrien
204991041Sobrien  if (last_file == NULL)
205091041Sobrien    {
205191041Sobrien      filestart = bfd_ardata (archive)->first_file_filepos;
205291041Sobrien    }
205391041Sobrien  else
205491041Sobrien    {
2055104834Sobrien      filestart = bfd_scan_vma (arch_xhdr_big (last_file)->nextoff,
2056104834Sobrien				(const char **) NULL, 10);
205791041Sobrien    }
2058104834Sobrien
205991041Sobrien  if (filestart == 0
2060104834Sobrien      || filestart == bfd_scan_vma (xcoff_ardata_big (archive)->memoff,
2061104834Sobrien				    (const char **) NULL, 10)
2062104834Sobrien      || filestart == bfd_scan_vma (xcoff_ardata_big (archive)->symoff,
2063104834Sobrien				    (const char **) NULL, 10))
206491041Sobrien    {
206591041Sobrien      bfd_set_error (bfd_error_no_more_archived_files);
206691041Sobrien      return NULL;
206791041Sobrien    }
206891041Sobrien
2069130561Sobrien  return _bfd_get_elt_at_filepos (archive, (file_ptr) filestart);
207091041Sobrien}
207191041Sobrien
207291041Sobrien/* We can't use the usual coff_sizeof_headers routine, because AIX
207391041Sobrien   always uses an a.out header.  */
207491041Sobrien
207591041Sobrienstatic int
2076218822Sdimxcoff64_sizeof_headers (bfd *abfd,
2077218822Sdim			struct bfd_link_info *info ATTRIBUTE_UNUSED)
207891041Sobrien{
207991041Sobrien  int size;
208091041Sobrien
208191041Sobrien  size = bfd_coff_filhsz (abfd);
208291041Sobrien
208391041Sobrien  /* Don't think the small aout header can be used since some of the
208491041Sobrien     old elements have been reordered past the end of the old coff
208591041Sobrien     small aout size.  */
208691041Sobrien
208791041Sobrien  if (xcoff_data (abfd)->full_aouthdr)
208891041Sobrien    size += bfd_coff_aoutsz (abfd);
208991041Sobrien
209091041Sobrien  size += abfd->section_count * bfd_coff_scnhsz (abfd);
209191041Sobrien  return size;
209291041Sobrien}
209391041Sobrien
209491041Sobrien
209591041Sobrien
209691041Sobrienstatic asection *
209791041Sobrienxcoff64_create_csect_from_smclas (abfd, aux, symbol_name)
209891041Sobrien     bfd *abfd;
209991041Sobrien     union internal_auxent *aux;
210091041Sobrien     const char *symbol_name;
210191041Sobrien{
210291041Sobrien  asection *return_value = NULL;
210391041Sobrien
210491041Sobrien  /* Changes from 32 :
210591041Sobrien     .sv == 8, is only for 32 bit programs
210691041Sobrien     .ti == 12 and .tb == 13 are now reserved.  */
210791041Sobrien  static const char *names[19] =
210891041Sobrien  {
210991041Sobrien    ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
211091041Sobrien    NULL, ".bs", ".ds", ".uc", NULL,  NULL,  NULL,  ".tc0",
211191041Sobrien    ".td", ".sv64", ".sv3264"
211291041Sobrien  };
211391041Sobrien
211491041Sobrien  if ((19 >= aux->x_csect.x_smclas)
211591041Sobrien      && (NULL != names[aux->x_csect.x_smclas]))
211691041Sobrien    {
211791041Sobrien
211891041Sobrien      return_value = bfd_make_section_anyway
211991041Sobrien	(abfd, names[aux->x_csect.x_smclas]);
212091041Sobrien
212191041Sobrien    }
212291041Sobrien  else
212391041Sobrien    {
212491041Sobrien      (*_bfd_error_handler)
2125218822Sdim	(_("%B: symbol `%s' has unrecognized smclas %d"),
2126218822Sdim	 abfd, symbol_name, aux->x_csect.x_smclas);
212791041Sobrien      bfd_set_error (bfd_error_bad_value);
212891041Sobrien    }
212991041Sobrien
213091041Sobrien  return return_value;
213191041Sobrien}
213291041Sobrien
2133130561Sobrienstatic bfd_boolean
213491041Sobrienxcoff64_is_lineno_count_overflow (abfd, value)
213591041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
213691041Sobrien     bfd_vma value ATTRIBUTE_UNUSED;
213791041Sobrien{
2138130561Sobrien  return FALSE;
213991041Sobrien}
214091041Sobrien
2141130561Sobrienstatic bfd_boolean
214291041Sobrienxcoff64_is_reloc_count_overflow (abfd, value)
214391041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
214491041Sobrien     bfd_vma value ATTRIBUTE_UNUSED;
214591041Sobrien{
2146130561Sobrien  return FALSE;
214791041Sobrien}
214891041Sobrien
214991041Sobrienstatic bfd_vma
215091041Sobrienxcoff64_loader_symbol_offset (abfd, ldhdr)
215191041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
215291041Sobrien     struct internal_ldhdr *ldhdr;
215391041Sobrien{
215491041Sobrien  return (ldhdr->l_symoff);
215591041Sobrien}
215691041Sobrien
215791041Sobrienstatic bfd_vma
215891041Sobrienxcoff64_loader_reloc_offset (abfd, ldhdr)
215991041Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
216091041Sobrien     struct internal_ldhdr *ldhdr;
216191041Sobrien{
216291041Sobrien  return (ldhdr->l_rldoff);
216391041Sobrien}
216491041Sobrien
2165130561Sobrienstatic bfd_boolean
2166104834Sobrienxcoff64_bad_format_hook (abfd, filehdr)
2167104834Sobrien     bfd * abfd;
2168104834Sobrien     PTR filehdr;
2169104834Sobrien{
2170104834Sobrien  struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
2171104834Sobrien
2172104834Sobrien  /* Check flavor first.  */
2173104834Sobrien  if (bfd_get_flavour (abfd) != bfd_target_xcoff_flavour)
2174130561Sobrien    return FALSE;
2175104834Sobrien
2176104834Sobrien  if (bfd_xcoff_magic_number (abfd) != internal_f->f_magic)
2177130561Sobrien    return FALSE;
2178104834Sobrien
2179130561Sobrien  return TRUE;
2180104834Sobrien}
2181104834Sobrien
2182130561Sobrienstatic bfd_boolean
2183104834Sobrienxcoff64_generate_rtinit (abfd, init, fini, rtld)
218491041Sobrien     bfd *abfd;
218591041Sobrien     const char *init;
218691041Sobrien     const char *fini;
2187130561Sobrien     bfd_boolean rtld;
218891041Sobrien{
218991041Sobrien  bfd_byte filehdr_ext[FILHSZ];
2190104834Sobrien  bfd_byte scnhdr_ext[SCNHSZ * 3];
2191104834Sobrien  bfd_byte syment_ext[SYMESZ * 10];
2192104834Sobrien  bfd_byte reloc_ext[RELSZ * 3];
219391041Sobrien  bfd_byte *data_buffer;
219491041Sobrien  bfd_size_type data_buffer_size;
219591041Sobrien  bfd_byte *string_table, *st_tmp;
219691041Sobrien  bfd_size_type string_table_size;
219791041Sobrien  bfd_vma val;
219891041Sobrien  size_t initsz, finisz;
219991041Sobrien  struct internal_filehdr filehdr;
2200104834Sobrien  struct internal_scnhdr text_scnhdr;
2201104834Sobrien  struct internal_scnhdr data_scnhdr;
2202104834Sobrien  struct internal_scnhdr bss_scnhdr;
220391041Sobrien  struct internal_syment syment;
220491041Sobrien  union internal_auxent auxent;
220591041Sobrien  struct internal_reloc reloc;
2206104834Sobrien
2207104834Sobrien  char *text_name = ".text";
220891041Sobrien  char *data_name = ".data";
2209104834Sobrien  char *bss_name = ".bss";
221091041Sobrien  char *rtinit_name = "__rtinit";
2211104834Sobrien  char *rtld_name = "__rtld";
2212104834Sobrien
2213104834Sobrien  if (! bfd_xcoff_rtinit_size (abfd))
2214130561Sobrien    return FALSE;
221591041Sobrien
221691041Sobrien  initsz = (init == NULL ? 0 : 1 + strlen (init));
221791041Sobrien  finisz = (fini == NULL ? 0 : 1 + strlen (fini));
221891041Sobrien
2219104834Sobrien  /* File header.  */
222091041Sobrien  memset (filehdr_ext, 0, FILHSZ);
222191041Sobrien  memset (&filehdr, 0, sizeof (struct internal_filehdr));
222291041Sobrien  filehdr.f_magic = bfd_xcoff_magic_number (abfd);
2223104834Sobrien  filehdr.f_nscns = 3;
222491041Sobrien  filehdr.f_timdat = 0;
222591041Sobrien  filehdr.f_nsyms = 0;  /* at least 6, no more than 8 */
222691041Sobrien  filehdr.f_symptr = 0; /* set below */
222791041Sobrien  filehdr.f_opthdr = 0;
222891041Sobrien  filehdr.f_flags = 0;
222991041Sobrien
2230104834Sobrien  /* Section headers.  */
2231104834Sobrien  memset (scnhdr_ext, 0, 3 * SCNHSZ);
223291041Sobrien
2233104834Sobrien  /* Text.  */
2234104834Sobrien  memset (&text_scnhdr, 0, sizeof (struct internal_scnhdr));
2235104834Sobrien  memcpy (text_scnhdr.s_name, text_name, strlen (text_name));
2236104834Sobrien  text_scnhdr.s_paddr = 0;
2237104834Sobrien  text_scnhdr.s_vaddr = 0;
2238104834Sobrien  text_scnhdr.s_size = 0;
2239104834Sobrien  text_scnhdr.s_scnptr = 0;
2240104834Sobrien  text_scnhdr.s_relptr = 0;
2241104834Sobrien  text_scnhdr.s_lnnoptr = 0;
2242104834Sobrien  text_scnhdr.s_nreloc = 0;
2243104834Sobrien  text_scnhdr.s_nlnno = 0;
2244104834Sobrien  text_scnhdr.s_flags = STYP_TEXT;
2245104834Sobrien
2246104834Sobrien  /* Data.  */
2247104834Sobrien  memset (&data_scnhdr, 0, sizeof (struct internal_scnhdr));
2248104834Sobrien  memcpy (data_scnhdr.s_name, data_name, strlen (data_name));
2249104834Sobrien  data_scnhdr.s_paddr = 0;
2250104834Sobrien  data_scnhdr.s_vaddr = 0;
2251104834Sobrien  data_scnhdr.s_size = 0;    /* set below */
2252104834Sobrien  data_scnhdr.s_scnptr = FILHSZ + 3 * SCNHSZ;
2253104834Sobrien  data_scnhdr.s_relptr = 0;  /* set below */
2254104834Sobrien  data_scnhdr.s_lnnoptr = 0;
2255104834Sobrien  data_scnhdr.s_nreloc = 0;  /* either 1 or 2 */
2256104834Sobrien  data_scnhdr.s_nlnno = 0;
2257104834Sobrien  data_scnhdr.s_flags = STYP_DATA;
2258104834Sobrien
2259104834Sobrien  /* Bss.  */
2260104834Sobrien  memset (&bss_scnhdr, 0, sizeof (struct internal_scnhdr));
2261104834Sobrien  memcpy (bss_scnhdr.s_name, bss_name, strlen (bss_name));
2262104834Sobrien  bss_scnhdr.s_paddr = 0; /* set below */
2263104834Sobrien  bss_scnhdr.s_vaddr = 0; /* set below */
2264104834Sobrien  bss_scnhdr.s_size = 0;  /* set below */
2265104834Sobrien  bss_scnhdr.s_scnptr = 0;
2266104834Sobrien  bss_scnhdr.s_relptr = 0;
2267104834Sobrien  bss_scnhdr.s_lnnoptr = 0;
2268104834Sobrien  bss_scnhdr.s_nreloc = 0;
2269104834Sobrien  bss_scnhdr.s_nlnno = 0;
2270104834Sobrien  bss_scnhdr.s_flags = STYP_BSS;
2271104834Sobrien
2272104834Sobrien  /* .data
2273130561Sobrien     0x0000	      0x00000000 : rtl
2274130561Sobrien     0x0004	      0x00000000 :
2275130561Sobrien     0x0008	      0x00000018 : offset to init, or 0
2276130561Sobrien     0x000C	      0x00000038 : offset to fini, or 0
2277130561Sobrien     0x0010	      0x00000010 : size of descriptor
2278130561Sobrien     0x0014	      0x00000000 : pad
2279130561Sobrien     0x0018	      0x00000000 : init, needs a reloc
2280130561Sobrien     0x001C	      0x00000000 :
2281130561Sobrien     0x0020	      0x00000058 : offset to init name
2282130561Sobrien     0x0024	      0x00000000 : flags, padded to a word
2283130561Sobrien     0x0028	      0x00000000 : empty init
2284130561Sobrien     0x002C	      0x00000000 :
2285130561Sobrien     0x0030	      0x00000000 :
2286130561Sobrien     0x0034	      0x00000000 :
2287130561Sobrien     0x0038	      0x00000000 : fini, needs a reloc
2288130561Sobrien     0x003C	      0x00000000 :
2289130561Sobrien     0x0040	      0x00000??? : offset to fini name
2290130561Sobrien     0x0044	      0x00000000 : flags, padded to a word
2291130561Sobrien     0x0048	      0x00000000 : empty fini
2292130561Sobrien     0x004C	      0x00000000 :
2293130561Sobrien     0x0050	      0x00000000 :
2294130561Sobrien     0x0054	      0x00000000 :
2295130561Sobrien     0x0058	      init name
229691041Sobrien     0x0058 + initsz  fini name */
229791041Sobrien
229891041Sobrien  data_buffer_size = 0x0058 + initsz + finisz;
2299130561Sobrien  data_buffer_size = (data_buffer_size + 7) &~ (bfd_size_type) 7;
230091041Sobrien  data_buffer = NULL;
2301104834Sobrien  data_buffer = (bfd_byte *) bfd_zmalloc (data_buffer_size);
230291041Sobrien  if (data_buffer == NULL)
2303130561Sobrien    return FALSE;
230491041Sobrien
2305104834Sobrien  if (initsz)
230691041Sobrien    {
230791041Sobrien      val = 0x18;
230891041Sobrien      bfd_put_32 (abfd, val, &data_buffer[0x08]);
230991041Sobrien      val = 0x58;
231091041Sobrien      bfd_put_32 (abfd, val, &data_buffer[0x20]);
231191041Sobrien      memcpy (&data_buffer[val], init, initsz);
231291041Sobrien    }
231391041Sobrien
2314104834Sobrien  if (finisz)
231591041Sobrien    {
231691041Sobrien      val = 0x38;
231791041Sobrien      bfd_put_32 (abfd, val, &data_buffer[0x0C]);
231891041Sobrien      val = 0x58 + initsz;
231991041Sobrien      bfd_put_32 (abfd, val, &data_buffer[0x40]);
232091041Sobrien      memcpy (&data_buffer[val], fini, finisz);
232191041Sobrien    }
232291041Sobrien
232391041Sobrien  val = 0x10;
232491041Sobrien  bfd_put_32 (abfd, val, &data_buffer[0x10]);
2325104834Sobrien  data_scnhdr.s_size = data_buffer_size;
2326104834Sobrien  bss_scnhdr.s_paddr = bss_scnhdr.s_vaddr = data_scnhdr.s_size;
232791041Sobrien
2328104834Sobrien  /* String table.  */
232991041Sobrien  string_table_size = 4;
233091041Sobrien  string_table_size += strlen (data_name) + 1;
233191041Sobrien  string_table_size += strlen (rtinit_name) + 1;
233291041Sobrien  string_table_size += initsz;
233391041Sobrien  string_table_size += finisz;
2334104834Sobrien  if (rtld)
2335104834Sobrien    string_table_size += strlen (rtld_name) + 1;
233691041Sobrien
2337104834Sobrien  string_table = (bfd_byte *) bfd_zmalloc (string_table_size);
2338104834Sobrien  if (string_table == NULL)
2339130561Sobrien    return FALSE;
2340104834Sobrien
234191041Sobrien  val = string_table_size;
234291041Sobrien  bfd_put_32 (abfd, val, &string_table[0]);
234391041Sobrien  st_tmp = string_table + 4;
2344104834Sobrien
2345104834Sobrien  /* symbols
234691041Sobrien     0. .data csect
234791041Sobrien     2. __rtinit
2348104834Sobrien     4. init function
2349104834Sobrien     6. fini function
2350104834Sobrien     8. __rtld  */
2351104834Sobrien  memset (syment_ext, 0, 10 * SYMESZ);
2352104834Sobrien  memset (reloc_ext, 0, 3 * RELSZ);
235391041Sobrien
235491041Sobrien  /* .data csect */
235591041Sobrien  memset (&syment, 0, sizeof (struct internal_syment));
235691041Sobrien  memset (&auxent, 0, sizeof (union internal_auxent));
235791041Sobrien
235891041Sobrien  syment._n._n_n._n_offset = st_tmp - string_table;
235991041Sobrien  memcpy (st_tmp, data_name, strlen (data_name));
236091041Sobrien  st_tmp += strlen (data_name) + 1;
236191041Sobrien
2362104834Sobrien  syment.n_scnum = 2;
236391041Sobrien  syment.n_sclass = C_HIDEXT;
236491041Sobrien  syment.n_numaux = 1;
236591041Sobrien  auxent.x_csect.x_scnlen.l = data_buffer_size;
236691041Sobrien  auxent.x_csect.x_smtyp = 3 << 3 | XTY_SD;
236791041Sobrien  auxent.x_csect.x_smclas = XMC_RW;
2368104834Sobrien  bfd_coff_swap_sym_out (abfd, &syment,
236991041Sobrien			 &syment_ext[filehdr.f_nsyms * SYMESZ]);
2370104834Sobrien  bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
2371104834Sobrien			 syment.n_numaux,
237291041Sobrien			 &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
237391041Sobrien  filehdr.f_nsyms += 2;
237491041Sobrien
237591041Sobrien  /* __rtinit */
237691041Sobrien  memset (&syment, 0, sizeof (struct internal_syment));
237791041Sobrien  memset (&auxent, 0, sizeof (union internal_auxent));
237891041Sobrien  syment._n._n_n._n_offset = st_tmp - string_table;
237991041Sobrien  memcpy (st_tmp, rtinit_name, strlen (rtinit_name));
238091041Sobrien  st_tmp += strlen (rtinit_name) + 1;
2381104834Sobrien
2382104834Sobrien  syment.n_scnum = 2;
238391041Sobrien  syment.n_sclass = C_EXT;
238491041Sobrien  syment.n_numaux = 1;
238591041Sobrien  auxent.x_csect.x_smtyp = XTY_LD;
238691041Sobrien  auxent.x_csect.x_smclas = XMC_RW;
2387104834Sobrien  bfd_coff_swap_sym_out (abfd, &syment,
238891041Sobrien			 &syment_ext[filehdr.f_nsyms * SYMESZ]);
2389104834Sobrien  bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
2390104834Sobrien			 syment.n_numaux,
239191041Sobrien			 &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
239291041Sobrien  filehdr.f_nsyms += 2;
239391041Sobrien
2394104834Sobrien  /* Init.  */
2395104834Sobrien  if (initsz)
239691041Sobrien    {
239791041Sobrien      memset (&syment, 0, sizeof (struct internal_syment));
239891041Sobrien      memset (&auxent, 0, sizeof (union internal_auxent));
239991041Sobrien
240091041Sobrien      syment._n._n_n._n_offset = st_tmp - string_table;
240191041Sobrien      memcpy (st_tmp, init, initsz);
240291041Sobrien      st_tmp += initsz;
240391041Sobrien
240491041Sobrien      syment.n_sclass = C_EXT;
240591041Sobrien      syment.n_numaux = 1;
2406104834Sobrien      bfd_coff_swap_sym_out (abfd, &syment,
240791041Sobrien			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
2408104834Sobrien      bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
2409104834Sobrien			     syment.n_numaux,
241091041Sobrien			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
2411104834Sobrien      /* Reloc.  */
241291041Sobrien      memset (&reloc, 0, sizeof (struct internal_reloc));
241391041Sobrien      reloc.r_vaddr = 0x0018;
241491041Sobrien      reloc.r_symndx = filehdr.f_nsyms;
241591041Sobrien      reloc.r_type = R_POS;
241691041Sobrien      reloc.r_size = 63;
241791041Sobrien      bfd_coff_swap_reloc_out (abfd, &reloc, &reloc_ext[0]);
241891041Sobrien
241991041Sobrien      filehdr.f_nsyms += 2;
2420104834Sobrien      data_scnhdr.s_nreloc += 1;
242191041Sobrien    }
242291041Sobrien
2423104834Sobrien  /* Finit.  */
2424104834Sobrien  if (finisz)
242591041Sobrien    {
242691041Sobrien      memset (&syment, 0, sizeof (struct internal_syment));
242791041Sobrien      memset (&auxent, 0, sizeof (union internal_auxent));
242891041Sobrien
242991041Sobrien      syment._n._n_n._n_offset = st_tmp - string_table;
243091041Sobrien      memcpy (st_tmp, fini, finisz);
243191041Sobrien      st_tmp += finisz;
243291041Sobrien
243391041Sobrien      syment.n_sclass = C_EXT;
243491041Sobrien      syment.n_numaux = 1;
2435104834Sobrien      bfd_coff_swap_sym_out (abfd, &syment,
243691041Sobrien			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
2437104834Sobrien      bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
2438104834Sobrien			     syment.n_numaux,
243991041Sobrien			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
244091041Sobrien
2441104834Sobrien      /* Reloc.  */
244291041Sobrien      memset (&reloc, 0, sizeof (struct internal_reloc));
244391041Sobrien      reloc.r_vaddr = 0x0038;
244491041Sobrien      reloc.r_symndx = filehdr.f_nsyms;
244591041Sobrien      reloc.r_type = R_POS;
244691041Sobrien      reloc.r_size = 63;
2447104834Sobrien      bfd_coff_swap_reloc_out (abfd, &reloc,
2448104834Sobrien			       &reloc_ext[data_scnhdr.s_nreloc * RELSZ]);
244991041Sobrien
245091041Sobrien      filehdr.f_nsyms += 2;
2451104834Sobrien      data_scnhdr.s_nreloc += 1;
245291041Sobrien    }
245391041Sobrien
2454104834Sobrien  if (rtld)
2455104834Sobrien    {
2456104834Sobrien      memset (&syment, 0, sizeof (struct internal_syment));
2457104834Sobrien      memset (&auxent, 0, sizeof (union internal_auxent));
245891041Sobrien
2459104834Sobrien      syment._n._n_n._n_offset = st_tmp - string_table;
2460104834Sobrien      memcpy (st_tmp, rtld_name, strlen (rtld_name));
2461104834Sobrien      st_tmp += strlen (rtld_name) + 1;
2462104834Sobrien
2463104834Sobrien      syment.n_sclass = C_EXT;
2464104834Sobrien      syment.n_numaux = 1;
2465104834Sobrien      bfd_coff_swap_sym_out (abfd, &syment,
2466104834Sobrien			     &syment_ext[filehdr.f_nsyms * SYMESZ]);
2467104834Sobrien      bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
2468104834Sobrien			     syment.n_numaux,
2469104834Sobrien			     &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
2470104834Sobrien
2471104834Sobrien      /* Reloc.  */
2472104834Sobrien      memset (&reloc, 0, sizeof (struct internal_reloc));
2473104834Sobrien      reloc.r_vaddr = 0x0000;
2474104834Sobrien      reloc.r_symndx = filehdr.f_nsyms;
2475104834Sobrien      reloc.r_type = R_POS;
2476104834Sobrien      reloc.r_size = 63;
2477104834Sobrien      bfd_coff_swap_reloc_out (abfd, &reloc,
2478104834Sobrien			       &reloc_ext[data_scnhdr.s_nreloc * RELSZ]);
2479104834Sobrien
2480104834Sobrien      filehdr.f_nsyms += 2;
2481104834Sobrien      data_scnhdr.s_nreloc += 1;
2482104834Sobrien
2483104834Sobrien      bss_scnhdr.s_size = 0;
2484104834Sobrien    }
2485104834Sobrien
2486104834Sobrien  data_scnhdr.s_relptr = data_scnhdr.s_scnptr + data_buffer_size;
2487104834Sobrien  filehdr.f_symptr = data_scnhdr.s_relptr + data_scnhdr.s_nreloc * RELSZ;
2488104834Sobrien
248991041Sobrien  bfd_coff_swap_filehdr_out (abfd, &filehdr, filehdr_ext);
249091041Sobrien  bfd_bwrite (filehdr_ext, FILHSZ, abfd);
2491104834Sobrien  bfd_coff_swap_scnhdr_out (abfd, &text_scnhdr, &scnhdr_ext[SCNHSZ * 0]);
2492104834Sobrien  bfd_coff_swap_scnhdr_out (abfd, &data_scnhdr, &scnhdr_ext[SCNHSZ * 1]);
2493104834Sobrien  bfd_coff_swap_scnhdr_out (abfd, &bss_scnhdr, &scnhdr_ext[SCNHSZ * 2]);
2494104834Sobrien  bfd_bwrite (scnhdr_ext, 3 * SCNHSZ, abfd);
249591041Sobrien  bfd_bwrite (data_buffer, data_buffer_size, abfd);
2496104834Sobrien  bfd_bwrite (reloc_ext, data_scnhdr.s_nreloc * RELSZ, abfd);
249791041Sobrien  bfd_bwrite (syment_ext, filehdr.f_nsyms * SYMESZ, abfd);
249891041Sobrien  bfd_bwrite (string_table, string_table_size, abfd);
249991041Sobrien
250091041Sobrien  free (data_buffer);
250191041Sobrien  data_buffer = NULL;
250291041Sobrien
2503130561Sobrien  return TRUE;
250491041Sobrien}
250591041Sobrien
250691041Sobrien/* The typical dynamic reloc.  */
250791041Sobrien
250891041Sobrienstatic reloc_howto_type xcoff64_dynamic_reloc =
250991041SobrienHOWTO (0,			/* type */
251091041Sobrien       0,			/* rightshift */
251191041Sobrien       4,			/* size (0 = byte, 1 = short, 2 = long) */
251291041Sobrien       64,			/* bitsize */
2513130561Sobrien       FALSE,			/* pc_relative */
251491041Sobrien       0,			/* bitpos */
251591041Sobrien       complain_overflow_bitfield, /* complain_on_overflow */
251691041Sobrien       0,			/* special_function */
251791041Sobrien       "R_POS",			/* name */
2518130561Sobrien       TRUE,			/* partial_inplace */
251991041Sobrien       MINUS_ONE,		/* src_mask */
252091041Sobrien       MINUS_ONE,		/* dst_mask */
2521130561Sobrien       FALSE);			/* pcrel_offset */
252291041Sobrien
252391041Sobrienstatic unsigned long xcoff64_glink_code[10] =
252491041Sobrien{
2525104834Sobrien  0xe9820000,	/* ld r12,0(r2) */
2526104834Sobrien  0xf8410028,	/* std r2,40(r1) */
2527104834Sobrien  0xe80c0000,	/* ld r0,0(r12) */
2528104834Sobrien  0xe84c0008,	/* ld r0,8(r12) */
2529104834Sobrien  0x7c0903a6,	/* mtctr r0 */
2530104834Sobrien  0x4e800420,	/* bctr */
2531104834Sobrien  0x00000000,	/* start of traceback table */
2532104834Sobrien  0x000ca000,	/* traceback table */
2533104834Sobrien  0x00000000,	/* traceback table */
2534104834Sobrien  0x00000018,	/* ??? */
253591041Sobrien};
253691041Sobrien
253791041Sobrienstatic const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
2538130561Sobrien  {
2539130561Sobrien    { /* COFF backend, defined in libcoff.h.  */
2540104834Sobrien      _bfd_xcoff64_swap_aux_in,
2541104834Sobrien      _bfd_xcoff64_swap_sym_in,
2542104834Sobrien      _bfd_xcoff64_swap_lineno_in,
2543104834Sobrien      _bfd_xcoff64_swap_aux_out,
2544104834Sobrien      _bfd_xcoff64_swap_sym_out,
2545104834Sobrien      _bfd_xcoff64_swap_lineno_out,
2546104834Sobrien      xcoff64_swap_reloc_out,
2547104834Sobrien      coff_swap_filehdr_out,
2548104834Sobrien      coff_swap_aouthdr_out,
2549104834Sobrien      coff_swap_scnhdr_out,
2550104834Sobrien      FILHSZ,
2551104834Sobrien      AOUTSZ,
2552104834Sobrien      SCNHSZ,
2553104834Sobrien      SYMESZ,
2554104834Sobrien      AUXESZ,
2555104834Sobrien      RELSZ,
2556104834Sobrien      LINESZ,
2557104834Sobrien      FILNMLEN,
2558130561Sobrien      TRUE,			/* _bfd_coff_long_filenames */
2559130561Sobrien      FALSE,			/* _bfd_coff_long_section_names */
2560104834Sobrien      3,			/* _bfd_coff_default_section_alignment_power */
2561130561Sobrien      TRUE,			/* _bfd_coff_force_symnames_in_strings */
2562130561Sobrien      4,			/* _bfd_coff_debug_string_prefix_length */
2563104834Sobrien      coff_swap_filehdr_in,
2564104834Sobrien      coff_swap_aouthdr_in,
2565104834Sobrien      coff_swap_scnhdr_in,
2566104834Sobrien      xcoff64_swap_reloc_in,
2567104834Sobrien      xcoff64_bad_format_hook,
2568104834Sobrien      coff_set_arch_mach_hook,
2569104834Sobrien      coff_mkobject_hook,
2570104834Sobrien      styp_to_sec_flags,
2571104834Sobrien      coff_set_alignment_hook,
2572104834Sobrien      coff_slurp_symbol_table,
2573104834Sobrien      symname_in_debug_hook,
2574104834Sobrien      coff_pointerize_aux_hook,
2575104834Sobrien      coff_print_aux,
2576104834Sobrien      dummy_reloc16_extra_cases,
2577104834Sobrien      dummy_reloc16_estimate,
2578130561Sobrien      NULL,			/* bfd_coff_sym_is_global */
2579130561Sobrien      coff_compute_section_file_positions,
2580130561Sobrien      NULL,			/* _bfd_coff_start_final_link */
2581104834Sobrien      xcoff64_ppc_relocate_section,
2582104834Sobrien      coff_rtype_to_howto,
2583104834Sobrien      NULL,			/* _bfd_coff_adjust_symndx */
2584104834Sobrien      _bfd_generic_link_add_one_symbol,
2585104834Sobrien      coff_link_output_has_begun,
2586104834Sobrien      coff_final_link_postscript
2587130561Sobrien    },
258891041Sobrien
2589130561Sobrien    0x01EF,			/* magic number */
2590104834Sobrien    bfd_arch_powerpc,
2591104834Sobrien    bfd_mach_ppc_620,
259291041Sobrien
2593130561Sobrien    /* Function pointers to xcoff specific swap routines.  */
2594104834Sobrien    xcoff64_swap_ldhdr_in,
2595104834Sobrien    xcoff64_swap_ldhdr_out,
2596104834Sobrien    xcoff64_swap_ldsym_in,
2597104834Sobrien    xcoff64_swap_ldsym_out,
2598104834Sobrien    xcoff64_swap_ldrel_in,
2599104834Sobrien    xcoff64_swap_ldrel_out,
260091041Sobrien
2601130561Sobrien    /* Sizes.  */
2602104834Sobrien    LDHDRSZ,
2603104834Sobrien    LDSYMSZ,
2604104834Sobrien    LDRELSZ,
2605130561Sobrien    24,				/* _xcoff_function_descriptor_size */
2606130561Sobrien    0,				/* _xcoff_small_aout_header_size */
260791041Sobrien
2608130561Sobrien    /* Versions.  */
2609130561Sobrien    2,				/* _xcoff_ldhdr_version */
261091041Sobrien
2611104834Sobrien    _bfd_xcoff64_put_symbol_name,
2612104834Sobrien    _bfd_xcoff64_put_ldsymbol_name,
2613130561Sobrien    &xcoff64_dynamic_reloc,
2614130561Sobrien    xcoff64_create_csect_from_smclas,
261591041Sobrien
2616130561Sobrien    /* Lineno and reloc count overflow.  */
2617130561Sobrien    xcoff64_is_lineno_count_overflow,
2618130561Sobrien    xcoff64_is_reloc_count_overflow,
261991041Sobrien
2620130561Sobrien    xcoff64_loader_symbol_offset,
2621130561Sobrien    xcoff64_loader_reloc_offset,
262291041Sobrien
2623130561Sobrien    /* glink.  */
2624130561Sobrien    &xcoff64_glink_code[0],
2625130561Sobrien    40,				/* _xcoff_glink_size */
262691041Sobrien
2627130561Sobrien    /* rtinit.  */
2628130561Sobrien    88,				/* _xcoff_rtinit_size */
2629104834Sobrien    xcoff64_generate_rtinit,
2630130561Sobrien  };
263191041Sobrien
2632104834Sobrien/* The transfer vector that leads the outside world to all of the above.  */
263391041Sobrienconst bfd_target rs6000coff64_vec =
2634130561Sobrien  {
2635130561Sobrien    "aixcoff64-rs6000",
2636130561Sobrien    bfd_target_xcoff_flavour,
2637130561Sobrien    BFD_ENDIAN_BIG,		/* data byte order is big */
2638130561Sobrien    BFD_ENDIAN_BIG,		/* header byte order is big */
263991041Sobrien
2640104834Sobrien    (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC
2641104834Sobrien     | HAS_SYMS | HAS_LOCALS | WP_TEXT),
264291041Sobrien
2643130561Sobrien    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA,
2644130561Sobrien    0,				/* leading char */
2645130561Sobrien    '/',			/* ar_pad_char */
2646104834Sobrien    15,				/* ar_max_namelen */
264791041Sobrien
2648130561Sobrien    /* data */
2649104834Sobrien    bfd_getb64,
2650104834Sobrien    bfd_getb_signed_64,
2651104834Sobrien    bfd_putb64,
2652104834Sobrien    bfd_getb32,
2653104834Sobrien    bfd_getb_signed_32,
2654104834Sobrien    bfd_putb32,
2655104834Sobrien    bfd_getb16,
2656104834Sobrien    bfd_getb_signed_16,
2657104834Sobrien    bfd_putb16,
265891041Sobrien
2659130561Sobrien    /* hdrs */
2660104834Sobrien    bfd_getb64,
2661104834Sobrien    bfd_getb_signed_64,
2662104834Sobrien    bfd_putb64,
2663104834Sobrien    bfd_getb32,
2664104834Sobrien    bfd_getb_signed_32,
2665104834Sobrien    bfd_putb32,
2666104834Sobrien    bfd_getb16,
2667104834Sobrien    bfd_getb_signed_16,
2668104834Sobrien    bfd_putb16,
266991041Sobrien
2670130561Sobrien    { /* bfd_check_format */
2671130561Sobrien      _bfd_dummy_target,
2672130561Sobrien      coff_object_p,
2673130561Sobrien      xcoff64_archive_p,
2674130561Sobrien      CORE_FILE_P
2675130561Sobrien    },
267691041Sobrien
2677130561Sobrien    { /* bfd_set_format */
2678130561Sobrien      bfd_false,
2679130561Sobrien      coff_mkobject,
2680130561Sobrien      _bfd_generic_mkarchive,
2681130561Sobrien      bfd_false
2682130561Sobrien    },
268391041Sobrien
2684130561Sobrien    {/* bfd_write_contents */
2685130561Sobrien      bfd_false,
2686130561Sobrien      xcoff64_write_object_contents,
2687130561Sobrien      _bfd_xcoff_write_archive_contents,
2688130561Sobrien      bfd_false
2689130561Sobrien    },
269091041Sobrien
2691130561Sobrien    /* Generic */
2692104834Sobrien    bfd_true,
2693104834Sobrien    bfd_true,
2694104834Sobrien    coff_new_section_hook,
2695104834Sobrien    _bfd_generic_get_section_contents,
2696130561Sobrien    _bfd_generic_get_section_contents_in_window,
269791041Sobrien
2698130561Sobrien    /* Copy */
2699104834Sobrien    _bfd_xcoff_copy_private_bfd_data,
2700130561Sobrien    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
2701218822Sdim    _bfd_generic_init_private_section_data,
2702130561Sobrien    ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
2703130561Sobrien    ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
2704218822Sdim    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
2705130561Sobrien    ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
2706130561Sobrien    ((bfd_boolean (*) (bfd *, void * )) bfd_true),
270791041Sobrien
2708130561Sobrien    /* Core */
2709104834Sobrien    coff_core_file_failing_command,
2710104834Sobrien    coff_core_file_failing_signal,
2711104834Sobrien    coff_core_file_matches_executable_p,
271291041Sobrien
2713130561Sobrien    /* Archive */
2714104834Sobrien    xcoff64_slurp_armap,
2715104834Sobrien    bfd_false,
2716130561Sobrien    ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
2717104834Sobrien    bfd_dont_truncate_arname,
2718104834Sobrien    _bfd_xcoff_write_armap,
2719104834Sobrien    _bfd_xcoff_read_ar_hdr,
2720104834Sobrien    xcoff64_openr_next_archived_file,
2721104834Sobrien    _bfd_generic_get_elt_at_index,
2722104834Sobrien    _bfd_xcoff_stat_arch_elt,
2723104834Sobrien    bfd_true,
272491041Sobrien
2725130561Sobrien    /* Symbols */
2726104834Sobrien    coff_get_symtab_upper_bound,
2727130561Sobrien    coff_canonicalize_symtab,
2728104834Sobrien    coff_make_empty_symbol,
2729104834Sobrien    coff_print_symbol,
2730104834Sobrien    coff_get_symbol_info,
2731104834Sobrien    _bfd_xcoff_is_local_label_name,
2732218822Sdim    coff_bfd_is_target_special_symbol,
2733104834Sobrien    coff_get_lineno,
2734104834Sobrien    coff_find_nearest_line,
2735218822Sdim    _bfd_generic_find_line,
2736218822Sdim    coff_find_inliner_info,
2737104834Sobrien    coff_bfd_make_debug_symbol,
2738104834Sobrien    _bfd_generic_read_minisymbols,
2739104834Sobrien    _bfd_generic_minisymbol_to_symbol,
274091041Sobrien
2741130561Sobrien    /* Reloc */
2742104834Sobrien    coff_get_reloc_upper_bound,
2743104834Sobrien    coff_canonicalize_reloc,
2744104834Sobrien    xcoff64_reloc_type_lookup,
2745218822Sdim    xcoff64_reloc_name_lookup,
274691041Sobrien
2747130561Sobrien    /* Write */
2748104834Sobrien    coff_set_arch_mach,
2749104834Sobrien    coff_set_section_contents,
275091041Sobrien
2751130561Sobrien    /* Link */
2752104834Sobrien    xcoff64_sizeof_headers,
2753130561Sobrien    bfd_generic_get_relocated_section_contents,
2754104834Sobrien    bfd_generic_relax_section,
2755104834Sobrien    _bfd_xcoff_bfd_link_hash_table_create,
2756104834Sobrien    _bfd_generic_link_hash_table_free,
2757104834Sobrien    _bfd_xcoff_bfd_link_add_symbols,
2758104834Sobrien    _bfd_generic_link_just_syms,
2759104834Sobrien    _bfd_xcoff_bfd_final_link,
2760104834Sobrien    _bfd_generic_link_split_section,
2761104834Sobrien    bfd_generic_gc_sections,
2762104834Sobrien    bfd_generic_merge_sections,
2763218822Sdim    bfd_generic_is_group_section,
2764104834Sobrien    bfd_generic_discard_group,
2765218822Sdim    _bfd_generic_section_already_linked,
276691041Sobrien
2767130561Sobrien    /* Dynamic */
2768130561Sobrien    _bfd_xcoff_get_dynamic_symtab_upper_bound,
2769104834Sobrien    _bfd_xcoff_canonicalize_dynamic_symtab,
2770218822Sdim    _bfd_nodynamic_get_synthetic_symtab,
2771104834Sobrien    _bfd_xcoff_get_dynamic_reloc_upper_bound,
2772104834Sobrien    _bfd_xcoff_canonicalize_dynamic_reloc,
277391041Sobrien
2774130561Sobrien    /* Opposite endian version, none exists */
2775130561Sobrien    NULL,
277691041Sobrien
2777130561Sobrien    (void *) &bfd_xcoff_backend_data,
2778130561Sobrien  };
2779104834Sobrien
2780130561Sobrienextern const bfd_target *xcoff64_core_p
2781130561Sobrien  PARAMS ((bfd *));
2782130561Sobrienextern bfd_boolean xcoff64_core_file_matches_executable_p
2783130561Sobrien  PARAMS ((bfd *, bfd *));
2784130561Sobrienextern char *xcoff64_core_file_failing_command
2785130561Sobrien  PARAMS ((bfd *));
2786130561Sobrienextern int xcoff64_core_file_failing_signal
2787130561Sobrien  PARAMS ((bfd *));
2788104834Sobrien
2789104834Sobrien/* AIX 5 */
2790104834Sobrienstatic const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
2791130561Sobrien  {
2792130561Sobrien    { /* COFF backend, defined in libcoff.h.  */
2793104834Sobrien      _bfd_xcoff64_swap_aux_in,
2794104834Sobrien      _bfd_xcoff64_swap_sym_in,
2795104834Sobrien      _bfd_xcoff64_swap_lineno_in,
2796104834Sobrien      _bfd_xcoff64_swap_aux_out,
2797104834Sobrien      _bfd_xcoff64_swap_sym_out,
2798104834Sobrien      _bfd_xcoff64_swap_lineno_out,
2799104834Sobrien      xcoff64_swap_reloc_out,
2800104834Sobrien      coff_swap_filehdr_out,
2801104834Sobrien      coff_swap_aouthdr_out,
2802104834Sobrien      coff_swap_scnhdr_out,
2803104834Sobrien      FILHSZ,
2804104834Sobrien      AOUTSZ,
2805104834Sobrien      SCNHSZ,
2806104834Sobrien      SYMESZ,
2807104834Sobrien      AUXESZ,
2808104834Sobrien      RELSZ,
2809104834Sobrien      LINESZ,
2810104834Sobrien      FILNMLEN,
2811130561Sobrien      TRUE,			/* _bfd_coff_long_filenames */
2812130561Sobrien      FALSE,			/* _bfd_coff_long_section_names */
2813104834Sobrien      3,			/* _bfd_coff_default_section_alignment_power */
2814130561Sobrien      TRUE,			/* _bfd_coff_force_symnames_in_strings */
2815130561Sobrien      4,			/* _bfd_coff_debug_string_prefix_length */
2816104834Sobrien      coff_swap_filehdr_in,
2817104834Sobrien      coff_swap_aouthdr_in,
2818104834Sobrien      coff_swap_scnhdr_in,
2819104834Sobrien      xcoff64_swap_reloc_in,
2820104834Sobrien      xcoff64_bad_format_hook,
2821104834Sobrien      coff_set_arch_mach_hook,
2822104834Sobrien      coff_mkobject_hook,
2823104834Sobrien      styp_to_sec_flags,
2824104834Sobrien      coff_set_alignment_hook,
2825104834Sobrien      coff_slurp_symbol_table,
2826104834Sobrien      symname_in_debug_hook,
2827104834Sobrien      coff_pointerize_aux_hook,
2828104834Sobrien      coff_print_aux,
2829104834Sobrien      dummy_reloc16_extra_cases,
2830104834Sobrien      dummy_reloc16_estimate,
2831130561Sobrien      NULL,			/* bfd_coff_sym_is_global */
2832130561Sobrien      coff_compute_section_file_positions,
2833130561Sobrien      NULL,			/* _bfd_coff_start_final_link */
2834104834Sobrien      xcoff64_ppc_relocate_section,
2835104834Sobrien      coff_rtype_to_howto,
2836104834Sobrien      NULL,			/* _bfd_coff_adjust_symndx */
2837104834Sobrien      _bfd_generic_link_add_one_symbol,
2838104834Sobrien      coff_link_output_has_begun,
2839104834Sobrien      coff_final_link_postscript
2840130561Sobrien    },
2841104834Sobrien
2842130561Sobrien    U64_TOCMAGIC,		/* magic number */
2843104834Sobrien    bfd_arch_powerpc,
2844104834Sobrien    bfd_mach_ppc_620,
2845104834Sobrien
2846130561Sobrien    /* Function pointers to xcoff specific swap routines.  */
2847104834Sobrien    xcoff64_swap_ldhdr_in,
2848104834Sobrien    xcoff64_swap_ldhdr_out,
2849104834Sobrien    xcoff64_swap_ldsym_in,
2850104834Sobrien    xcoff64_swap_ldsym_out,
2851104834Sobrien    xcoff64_swap_ldrel_in,
2852104834Sobrien    xcoff64_swap_ldrel_out,
2853104834Sobrien
2854130561Sobrien    /* Sizes.  */
2855104834Sobrien    LDHDRSZ,
2856104834Sobrien    LDSYMSZ,
2857104834Sobrien    LDRELSZ,
2858130561Sobrien    24,				/* _xcoff_function_descriptor_size */
2859130561Sobrien    0,				/* _xcoff_small_aout_header_size */
2860130561Sobrien    /* Versions.  */
2861130561Sobrien    2,				/* _xcoff_ldhdr_version */
2862104834Sobrien
2863104834Sobrien    _bfd_xcoff64_put_symbol_name,
2864104834Sobrien    _bfd_xcoff64_put_ldsymbol_name,
2865130561Sobrien    &xcoff64_dynamic_reloc,
2866130561Sobrien    xcoff64_create_csect_from_smclas,
2867104834Sobrien
2868130561Sobrien    /* Lineno and reloc count overflow.  */
2869130561Sobrien    xcoff64_is_lineno_count_overflow,
2870130561Sobrien    xcoff64_is_reloc_count_overflow,
2871104834Sobrien
2872130561Sobrien    xcoff64_loader_symbol_offset,
2873130561Sobrien    xcoff64_loader_reloc_offset,
2874104834Sobrien
2875130561Sobrien    /* glink.  */
2876130561Sobrien    &xcoff64_glink_code[0],
2877130561Sobrien    40,				/* _xcoff_glink_size */
2878104834Sobrien
2879130561Sobrien    /* rtinit.  */
2880130561Sobrien    88,				/* _xcoff_rtinit_size */
2881104834Sobrien    xcoff64_generate_rtinit,
2882130561Sobrien  };
2883104834Sobrien
2884104834Sobrien/* The transfer vector that leads the outside world to all of the above.  */
2885104834Sobrienconst bfd_target aix5coff64_vec =
2886130561Sobrien  {
2887130561Sobrien    "aix5coff64-rs6000",
2888130561Sobrien    bfd_target_xcoff_flavour,
2889130561Sobrien    BFD_ENDIAN_BIG,		/* data byte order is big */
2890130561Sobrien    BFD_ENDIAN_BIG,		/* header byte order is big */
2891104834Sobrien
2892104834Sobrien    (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC
2893104834Sobrien     | HAS_SYMS | HAS_LOCALS | WP_TEXT),
2894104834Sobrien
2895130561Sobrien    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA,
2896130561Sobrien    0,				/* leading char */
2897130561Sobrien    '/',			/* ar_pad_char */
2898104834Sobrien    15,				/* ar_max_namelen */
2899104834Sobrien
2900130561Sobrien    /* data */
2901104834Sobrien    bfd_getb64,
2902104834Sobrien    bfd_getb_signed_64,
2903104834Sobrien    bfd_putb64,
2904104834Sobrien    bfd_getb32,
2905104834Sobrien    bfd_getb_signed_32,
2906104834Sobrien    bfd_putb32,
2907104834Sobrien    bfd_getb16,
2908104834Sobrien    bfd_getb_signed_16,
2909104834Sobrien    bfd_putb16,
2910104834Sobrien
2911130561Sobrien    /* hdrs */
2912104834Sobrien    bfd_getb64,
2913104834Sobrien    bfd_getb_signed_64,
2914104834Sobrien    bfd_putb64,
2915104834Sobrien    bfd_getb32,
2916104834Sobrien    bfd_getb_signed_32,
2917104834Sobrien    bfd_putb32,
2918104834Sobrien    bfd_getb16,
2919104834Sobrien    bfd_getb_signed_16,
2920104834Sobrien    bfd_putb16,
2921104834Sobrien
2922130561Sobrien    { /* bfd_check_format */
2923130561Sobrien      _bfd_dummy_target,
2924130561Sobrien      coff_object_p,
2925130561Sobrien      xcoff64_archive_p,
2926130561Sobrien      xcoff64_core_p
2927130561Sobrien    },
2928104834Sobrien
2929130561Sobrien    { /* bfd_set_format */
2930130561Sobrien      bfd_false,
2931130561Sobrien      coff_mkobject,
2932130561Sobrien      _bfd_generic_mkarchive,
2933130561Sobrien      bfd_false
2934130561Sobrien    },
2935104834Sobrien
2936130561Sobrien    {/* bfd_write_contents */
2937130561Sobrien      bfd_false,
2938130561Sobrien      xcoff64_write_object_contents,
2939130561Sobrien      _bfd_xcoff_write_archive_contents,
2940130561Sobrien      bfd_false
2941130561Sobrien    },
2942104834Sobrien
2943130561Sobrien    /* Generic */
2944104834Sobrien    bfd_true,
2945104834Sobrien    bfd_true,
2946104834Sobrien    coff_new_section_hook,
2947104834Sobrien    _bfd_generic_get_section_contents,
2948130561Sobrien    _bfd_generic_get_section_contents_in_window,
2949104834Sobrien
2950130561Sobrien    /* Copy */
2951104834Sobrien    _bfd_xcoff_copy_private_bfd_data,
2952130561Sobrien    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
2953218822Sdim    _bfd_generic_init_private_section_data,
2954130561Sobrien    ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
2955130561Sobrien    ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
2956218822Sdim    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
2957130561Sobrien    ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
2958130561Sobrien    ((bfd_boolean (*) (bfd *, void * )) bfd_true),
2959104834Sobrien
2960130561Sobrien    /* Core */
2961104834Sobrien    xcoff64_core_file_failing_command,
2962104834Sobrien    xcoff64_core_file_failing_signal,
2963104834Sobrien    xcoff64_core_file_matches_executable_p,
2964104834Sobrien
2965130561Sobrien    /* Archive */
2966104834Sobrien    xcoff64_slurp_armap,
2967104834Sobrien    bfd_false,
2968130561Sobrien    ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
2969104834Sobrien    bfd_dont_truncate_arname,
2970104834Sobrien    _bfd_xcoff_write_armap,
2971104834Sobrien    _bfd_xcoff_read_ar_hdr,
2972104834Sobrien    xcoff64_openr_next_archived_file,
2973104834Sobrien    _bfd_generic_get_elt_at_index,
2974104834Sobrien    _bfd_xcoff_stat_arch_elt,
2975104834Sobrien    bfd_true,
2976104834Sobrien
2977130561Sobrien    /* Symbols */
2978104834Sobrien    coff_get_symtab_upper_bound,
2979130561Sobrien    coff_canonicalize_symtab,
2980104834Sobrien    coff_make_empty_symbol,
2981104834Sobrien    coff_print_symbol,
2982104834Sobrien    coff_get_symbol_info,
2983104834Sobrien    _bfd_xcoff_is_local_label_name,
2984218822Sdim    coff_bfd_is_target_special_symbol,
2985104834Sobrien    coff_get_lineno,
2986104834Sobrien    coff_find_nearest_line,
2987218822Sdim    _bfd_generic_find_line,
2988218822Sdim    coff_find_inliner_info,
2989104834Sobrien    coff_bfd_make_debug_symbol,
2990104834Sobrien    _bfd_generic_read_minisymbols,
2991104834Sobrien    _bfd_generic_minisymbol_to_symbol,
2992104834Sobrien
2993130561Sobrien    /* Reloc */
2994104834Sobrien    coff_get_reloc_upper_bound,
2995104834Sobrien    coff_canonicalize_reloc,
2996104834Sobrien    xcoff64_reloc_type_lookup,
2997218822Sdim    xcoff64_reloc_name_lookup,
2998104834Sobrien
2999130561Sobrien    /* Write */
3000104834Sobrien    coff_set_arch_mach,
3001104834Sobrien    coff_set_section_contents,
3002104834Sobrien
3003130561Sobrien    /* Link */
3004104834Sobrien    xcoff64_sizeof_headers,
3005130561Sobrien    bfd_generic_get_relocated_section_contents,
3006104834Sobrien    bfd_generic_relax_section,
3007104834Sobrien    _bfd_xcoff_bfd_link_hash_table_create,
3008104834Sobrien    _bfd_generic_link_hash_table_free,
3009104834Sobrien    _bfd_xcoff_bfd_link_add_symbols,
3010104834Sobrien    _bfd_generic_link_just_syms,
3011104834Sobrien    _bfd_xcoff_bfd_final_link,
3012104834Sobrien    _bfd_generic_link_split_section,
3013104834Sobrien    bfd_generic_gc_sections,
3014104834Sobrien    bfd_generic_merge_sections,
3015218822Sdim    bfd_generic_is_group_section,
3016104834Sobrien    bfd_generic_discard_group,
3017218822Sdim    _bfd_generic_section_already_linked,
3018104834Sobrien
3019130561Sobrien    /* Dynamic */
3020130561Sobrien    _bfd_xcoff_get_dynamic_symtab_upper_bound,
3021104834Sobrien    _bfd_xcoff_canonicalize_dynamic_symtab,
3022218822Sdim    _bfd_nodynamic_get_synthetic_symtab,
3023104834Sobrien    _bfd_xcoff_get_dynamic_reloc_upper_bound,
3024104834Sobrien    _bfd_xcoff_canonicalize_dynamic_reloc,
3025104834Sobrien
3026130561Sobrien    /* Opposite endian version, none exists.  */
3027130561Sobrien    NULL,
3028104834Sobrien
3029130561Sobrien    (void *) & bfd_xcoff_aix5_backend_data,
3030130561Sobrien  };
3031