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, §ion, &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