184865Sobrien/* BFD back-end for IBM RS/6000 "XCOFF" files. 2218822Sdim Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 384865Sobrien Free Software Foundation, Inc. 4218822Sdim Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore. 584865Sobrien Archive support from Damon A. Permezel. 684865Sobrien Contributed by IBM Corporation and Cygnus Support. 784865Sobrien 884865SobrienThis file is part of BFD, the Binary File Descriptor library. 984865Sobrien 1084865SobrienThis program is free software; you can redistribute it and/or modify 1184865Sobrienit under the terms of the GNU General Public License as published by 1284865Sobrienthe Free Software Foundation; either version 2 of the License, or 1384865Sobrien(at your option) any later version. 1484865Sobrien 1584865SobrienThis program is distributed in the hope that it will be useful, 1684865Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1784865SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1884865SobrienGNU General Public License for more details. 1984865Sobrien 2084865SobrienYou should have received a copy of the GNU General Public License 2184865Sobrienalong with this program; if not, write to the Free Software 22218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2384865Sobrien 24218822Sdim#include "sysdep.h" 2584865Sobrien#include "bfd.h" 2689857Sobrien#include "bfdlink.h" 2784865Sobrien#include "libbfd.h" 2884865Sobrien#include "coff/internal.h" 2989857Sobrien#include "coff/xcoff.h" 3084865Sobrien#include "coff/rs6000.h" 3184865Sobrien#include "libcoff.h" 3289857Sobrien#include "libxcoff.h" 3384865Sobrien 34130561Sobrienextern bfd_boolean _bfd_xcoff_mkobject 35130561Sobrien PARAMS ((bfd *)); 36130561Sobrienextern bfd_boolean _bfd_xcoff_copy_private_bfd_data 37130561Sobrien PARAMS ((bfd *, bfd *)); 38130561Sobrienextern bfd_boolean _bfd_xcoff_is_local_label_name 39130561Sobrien PARAMS ((bfd *, const char *)); 4089857Sobrienextern reloc_howto_type *_bfd_xcoff_reloc_type_lookup 4189857Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 42130561Sobrienextern bfd_boolean _bfd_xcoff_slurp_armap 43130561Sobrien PARAMS ((bfd *)); 44130561Sobrienextern const bfd_target *_bfd_xcoff_archive_p 45130561Sobrien PARAMS ((bfd *)); 46130561Sobrienextern PTR _bfd_xcoff_read_ar_hdr 47130561Sobrien PARAMS ((bfd *)); 48130561Sobrienextern bfd *_bfd_xcoff_openr_next_archived_file 49130561Sobrien PARAMS ((bfd *, bfd *)); 50130561Sobrienextern int _bfd_xcoff_stat_arch_elt 51130561Sobrien PARAMS ((bfd *, struct stat *)); 52130561Sobrienextern bfd_boolean _bfd_xcoff_write_armap 5389857Sobrien PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); 54130561Sobrienextern bfd_boolean _bfd_xcoff_write_archive_contents 55130561Sobrien PARAMS ((bfd *)); 56130561Sobrienextern int _bfd_xcoff_sizeof_headers 57218822Sdim PARAMS ((bfd *, struct bfd_link_info *)); 58130561Sobrienextern void _bfd_xcoff_swap_sym_in 59130561Sobrien PARAMS ((bfd *, PTR, PTR)); 60130561Sobrienextern unsigned int _bfd_xcoff_swap_sym_out 61130561Sobrien PARAMS ((bfd *, PTR, PTR)); 62130561Sobrienextern void _bfd_xcoff_swap_aux_in 63130561Sobrien PARAMS ((bfd *, PTR, int, int, int, int, PTR)); 64130561Sobrienextern unsigned int _bfd_xcoff_swap_aux_out 65130561Sobrien PARAMS ((bfd *, PTR, int, int, int, int, PTR)); 66130561Sobrienstatic void xcoff_swap_reloc_in 67130561Sobrien PARAMS ((bfd *, PTR, PTR)); 68130561Sobrienstatic unsigned int xcoff_swap_reloc_out 69130561Sobrien PARAMS ((bfd *, PTR, PTR)); 7089857Sobrien 71104834Sobrien/* Forward declare xcoff_rtype2howto for coffcode.h macro. */ 72130561Sobrienvoid xcoff_rtype2howto 73130561Sobrien PARAMS ((arelent *, struct internal_reloc *)); 7489857Sobrien 7589857Sobrien/* coffcode.h needs these to be defined. */ 7689857Sobrien#define RS6000COFF_C 1 7789857Sobrien 7889857Sobrien#define SELECT_RELOC(internal, howto) \ 7989857Sobrien { \ 8089857Sobrien internal.r_type = howto->type; \ 8189857Sobrien internal.r_size = \ 8289857Sobrien ((howto->complain_on_overflow == complain_overflow_signed \ 8389857Sobrien ? 0x80 \ 8489857Sobrien : 0) \ 8589857Sobrien | (howto->bitsize - 1)); \ 8689857Sobrien } 8789857Sobrien 8889857Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) 8989857Sobrien#define COFF_LONG_FILENAMES 9089857Sobrien#define NO_COFF_SYMBOLS 91104834Sobrien#define RTYPE2HOWTO(cache_ptr, dst) xcoff_rtype2howto (cache_ptr, dst) 9289857Sobrien#define coff_mkobject _bfd_xcoff_mkobject 9389857Sobrien#define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data 9489857Sobrien#define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name 9589857Sobrien#define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup 96218822Sdim#define coff_bfd_reloc_name_lookup _bfd_xcoff_reloc_name_lookup 9789857Sobrien#ifdef AIX_CORE 98130561Sobrienextern const bfd_target * rs6000coff_core_p 99130561Sobrien PARAMS ((bfd *abfd)); 100130561Sobrienextern bfd_boolean rs6000coff_core_file_matches_executable_p 101104834Sobrien PARAMS ((bfd *cbfd, bfd *ebfd)); 102130561Sobrienextern char *rs6000coff_core_file_failing_command 103130561Sobrien PARAMS ((bfd *abfd)); 104130561Sobrienextern int rs6000coff_core_file_failing_signal 105130561Sobrien PARAMS ((bfd *abfd)); 10689857Sobrien#define CORE_FILE_P rs6000coff_core_p 10789857Sobrien#define coff_core_file_failing_command \ 10889857Sobrien rs6000coff_core_file_failing_command 10989857Sobrien#define coff_core_file_failing_signal \ 11089857Sobrien rs6000coff_core_file_failing_signal 11189857Sobrien#define coff_core_file_matches_executable_p \ 11289857Sobrien rs6000coff_core_file_matches_executable_p 11389857Sobrien#else 11489857Sobrien#define CORE_FILE_P _bfd_dummy_target 11589857Sobrien#define coff_core_file_failing_command \ 11689857Sobrien _bfd_nocore_core_file_failing_command 11789857Sobrien#define coff_core_file_failing_signal \ 11889857Sobrien _bfd_nocore_core_file_failing_signal 11989857Sobrien#define coff_core_file_matches_executable_p \ 12089857Sobrien _bfd_nocore_core_file_matches_executable_p 12189857Sobrien#endif 12289857Sobrien#define coff_SWAP_sym_in _bfd_xcoff_swap_sym_in 12389857Sobrien#define coff_SWAP_sym_out _bfd_xcoff_swap_sym_out 12489857Sobrien#define coff_SWAP_aux_in _bfd_xcoff_swap_aux_in 12589857Sobrien#define coff_SWAP_aux_out _bfd_xcoff_swap_aux_out 126104834Sobrien#define coff_swap_reloc_in xcoff_swap_reloc_in 127104834Sobrien#define coff_swap_reloc_out xcoff_swap_reloc_out 128104834Sobrien#define NO_COFF_RELOCS 12989857Sobrien 13089857Sobrien#include "coffcode.h" 13189857Sobrien 13284865Sobrien/* The main body of code is in coffcode.h. */ 13384865Sobrien 134130561Sobrienstatic const char *normalize_filename 135130561Sobrien PARAMS ((bfd *)); 136130561Sobrienstatic bfd_boolean xcoff_write_armap_old 13789857Sobrien PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); 138130561Sobrienstatic bfd_boolean xcoff_write_armap_big 13989857Sobrien PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); 140130561Sobrienstatic bfd_boolean xcoff_write_archive_contents_old 141130561Sobrien PARAMS ((bfd *)); 142130561Sobrienstatic bfd_boolean xcoff_write_archive_contents_big 143130561Sobrien PARAMS ((bfd *)); 14489857Sobrienstatic void xcoff_swap_ldhdr_in 14589857Sobrien PARAMS ((bfd *, const PTR, struct internal_ldhdr *)); 14689857Sobrienstatic void xcoff_swap_ldhdr_out 14789857Sobrien PARAMS ((bfd *, const struct internal_ldhdr *, PTR)); 14889857Sobrienstatic void xcoff_swap_ldsym_in 14989857Sobrien PARAMS ((bfd *, const PTR, struct internal_ldsym *)); 15089857Sobrienstatic void xcoff_swap_ldsym_out 15189857Sobrien PARAMS ((bfd *, const struct internal_ldsym *, PTR)); 15289857Sobrienstatic void xcoff_swap_ldrel_in 15389857Sobrien PARAMS ((bfd *, const PTR, struct internal_ldrel *)); 15489857Sobrienstatic void xcoff_swap_ldrel_out 15589857Sobrien PARAMS ((bfd *, const struct internal_ldrel *, PTR)); 156130561Sobrienstatic bfd_boolean xcoff_ppc_relocate_section 15789857Sobrien PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 15889857Sobrien struct internal_reloc *, struct internal_syment *, asection **)); 159130561Sobrienstatic bfd_boolean _bfd_xcoff_put_ldsymbol_name 16089857Sobrien PARAMS ((bfd *, struct xcoff_loader_info *, struct internal_ldsym *, 16189857Sobrien const char *)); 16289857Sobrienstatic asection *xcoff_create_csect_from_smclas 16389857Sobrien PARAMS ((bfd *, union internal_auxent *, const char *)); 164130561Sobrienstatic bfd_boolean xcoff_is_lineno_count_overflow 165130561Sobrien PARAMS ((bfd *, bfd_vma)); 166130561Sobrienstatic bfd_boolean xcoff_is_reloc_count_overflow 167130561Sobrien PARAMS ((bfd *, bfd_vma)); 16889857Sobrienstatic bfd_vma xcoff_loader_symbol_offset 16989857Sobrien PARAMS ((bfd *, struct internal_ldhdr *)); 17089857Sobrienstatic bfd_vma xcoff_loader_reloc_offset 17189857Sobrien PARAMS ((bfd *, struct internal_ldhdr *)); 172130561Sobrienstatic bfd_boolean xcoff_generate_rtinit 173130561Sobrien PARAMS ((bfd *, const char *, const char *, bfd_boolean)); 174130561Sobrienstatic bfd_boolean do_pad 175130561Sobrien PARAMS ((bfd *, unsigned int)); 176130561Sobrienstatic bfd_boolean do_copy 177130561Sobrien PARAMS ((bfd *, bfd *)); 178130561Sobrienstatic bfd_boolean do_shared_object_padding 179218822Sdim PARAMS ((bfd *, bfd *, file_ptr *, int)); 18084865Sobrien 181104834Sobrien/* Relocation functions */ 182130561Sobrienstatic bfd_boolean xcoff_reloc_type_br 183130561Sobrien PARAMS ((XCOFF_RELOC_FUNCTION_ARGS)); 18489857Sobrien 185130561Sobrienstatic bfd_boolean xcoff_complain_overflow_dont_func 186104834Sobrien PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)); 187130561Sobrienstatic bfd_boolean xcoff_complain_overflow_bitfield_func 188104834Sobrien PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)); 189130561Sobrienstatic bfd_boolean xcoff_complain_overflow_signed_func 190104834Sobrien PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)); 191130561Sobrienstatic bfd_boolean xcoff_complain_overflow_unsigned_func 192104834Sobrien PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)); 193104834Sobrien 194130561Sobrienbfd_boolean (*xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION]) 195104834Sobrien PARAMS ((XCOFF_RELOC_FUNCTION_ARGS)) = 196104834Sobrien{ 197130561Sobrien xcoff_reloc_type_pos, /* R_POS (0x00) */ 198130561Sobrien xcoff_reloc_type_neg, /* R_NEG (0x01) */ 199130561Sobrien xcoff_reloc_type_rel, /* R_REL (0x02) */ 200130561Sobrien xcoff_reloc_type_toc, /* R_TOC (0x03) */ 201104834Sobrien xcoff_reloc_type_fail, /* R_RTB (0x04) */ 202130561Sobrien xcoff_reloc_type_toc, /* R_GL (0x05) */ 203130561Sobrien xcoff_reloc_type_toc, /* R_TCL (0x06) */ 204130561Sobrien xcoff_reloc_type_fail, /* (0x07) */ 205130561Sobrien xcoff_reloc_type_ba, /* R_BA (0x08) */ 206130561Sobrien xcoff_reloc_type_fail, /* (0x09) */ 207130561Sobrien xcoff_reloc_type_br, /* R_BR (0x0a) */ 208130561Sobrien xcoff_reloc_type_fail, /* (0x0b) */ 209130561Sobrien xcoff_reloc_type_pos, /* R_RL (0x0c) */ 210130561Sobrien xcoff_reloc_type_pos, /* R_RLA (0x0d) */ 211130561Sobrien xcoff_reloc_type_fail, /* (0x0e) */ 212104834Sobrien xcoff_reloc_type_noop, /* R_REF (0x0f) */ 213130561Sobrien xcoff_reloc_type_fail, /* (0x10) */ 214130561Sobrien xcoff_reloc_type_fail, /* (0x11) */ 215130561Sobrien xcoff_reloc_type_toc, /* R_TRL (0x12) */ 216130561Sobrien xcoff_reloc_type_toc, /* R_TRLA (0x13) */ 217104834Sobrien xcoff_reloc_type_fail, /* R_RRTBI (0x14) */ 218104834Sobrien xcoff_reloc_type_fail, /* R_RRTBA (0x15) */ 219130561Sobrien xcoff_reloc_type_ba, /* R_CAI (0x16) */ 220104834Sobrien xcoff_reloc_type_crel, /* R_CREL (0x17) */ 221130561Sobrien xcoff_reloc_type_ba, /* R_RBA (0x18) */ 222130561Sobrien xcoff_reloc_type_ba, /* R_RBAC (0x19) */ 223130561Sobrien xcoff_reloc_type_br, /* R_RBR (0x1a) */ 224130561Sobrien xcoff_reloc_type_ba, /* R_RBRC (0x1b) */ 225104834Sobrien}; 226104834Sobrien 227130561Sobrienbfd_boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW]) 228104834Sobrien PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS)) = 229104834Sobrien{ 230104834Sobrien xcoff_complain_overflow_dont_func, 231104834Sobrien xcoff_complain_overflow_bitfield_func, 232104834Sobrien xcoff_complain_overflow_signed_func, 233104834Sobrien xcoff_complain_overflow_unsigned_func, 234104834Sobrien}; 235104834Sobrien 23684865Sobrien/* We use our own tdata type. Its first field is the COFF tdata type, 23784865Sobrien so the COFF routines are compatible. */ 23884865Sobrien 239130561Sobrienbfd_boolean 24084865Sobrien_bfd_xcoff_mkobject (abfd) 24184865Sobrien bfd *abfd; 24284865Sobrien{ 24384865Sobrien coff_data_type *coff; 24489857Sobrien bfd_size_type amt = sizeof (struct xcoff_tdata); 24584865Sobrien 24689857Sobrien abfd->tdata.xcoff_obj_data = (struct xcoff_tdata *) bfd_zalloc (abfd, amt); 24784865Sobrien if (abfd->tdata.xcoff_obj_data == NULL) 248130561Sobrien return FALSE; 24984865Sobrien coff = coff_data (abfd); 25084865Sobrien coff->symbols = (coff_symbol_type *) NULL; 25184865Sobrien coff->conversion_table = (unsigned int *) NULL; 25284865Sobrien coff->raw_syments = (struct coff_ptr_struct *) NULL; 25384865Sobrien coff->relocbase = 0; 25484865Sobrien 25584865Sobrien xcoff_data (abfd)->modtype = ('1' << 8) | 'L'; 25684865Sobrien 25784865Sobrien /* We set cputype to -1 to indicate that it has not been 25884865Sobrien initialized. */ 25984865Sobrien xcoff_data (abfd)->cputype = -1; 26084865Sobrien 26184865Sobrien xcoff_data (abfd)->csects = NULL; 26284865Sobrien xcoff_data (abfd)->debug_indices = NULL; 26384865Sobrien 26489857Sobrien /* text section alignment is different than the default */ 265104834Sobrien bfd_xcoff_text_align_power (abfd) = 2; 26689857Sobrien 267130561Sobrien return TRUE; 26884865Sobrien} 26984865Sobrien 27084865Sobrien/* Copy XCOFF data from one BFD to another. */ 27184865Sobrien 272130561Sobrienbfd_boolean 27384865Sobrien_bfd_xcoff_copy_private_bfd_data (ibfd, obfd) 27484865Sobrien bfd *ibfd; 27584865Sobrien bfd *obfd; 27684865Sobrien{ 27784865Sobrien struct xcoff_tdata *ix, *ox; 27884865Sobrien asection *sec; 27984865Sobrien 28084865Sobrien if (ibfd->xvec != obfd->xvec) 281130561Sobrien return TRUE; 28284865Sobrien ix = xcoff_data (ibfd); 28384865Sobrien ox = xcoff_data (obfd); 28484865Sobrien ox->full_aouthdr = ix->full_aouthdr; 28584865Sobrien ox->toc = ix->toc; 28684865Sobrien if (ix->sntoc == 0) 28784865Sobrien ox->sntoc = 0; 28884865Sobrien else 28984865Sobrien { 29084865Sobrien sec = coff_section_from_bfd_index (ibfd, ix->sntoc); 29184865Sobrien if (sec == NULL) 29284865Sobrien ox->sntoc = 0; 29384865Sobrien else 29484865Sobrien ox->sntoc = sec->output_section->target_index; 29584865Sobrien } 29684865Sobrien if (ix->snentry == 0) 29784865Sobrien ox->snentry = 0; 29884865Sobrien else 29984865Sobrien { 30084865Sobrien sec = coff_section_from_bfd_index (ibfd, ix->snentry); 30184865Sobrien if (sec == NULL) 30284865Sobrien ox->snentry = 0; 30384865Sobrien else 30484865Sobrien ox->snentry = sec->output_section->target_index; 30584865Sobrien } 306104834Sobrien bfd_xcoff_text_align_power (obfd) = bfd_xcoff_text_align_power (ibfd); 307104834Sobrien bfd_xcoff_data_align_power (obfd) = bfd_xcoff_data_align_power (ibfd); 30884865Sobrien ox->modtype = ix->modtype; 30984865Sobrien ox->cputype = ix->cputype; 31084865Sobrien ox->maxdata = ix->maxdata; 31184865Sobrien ox->maxstack = ix->maxstack; 312130561Sobrien return TRUE; 31384865Sobrien} 31484865Sobrien 31584865Sobrien/* I don't think XCOFF really has a notion of local labels based on 31684865Sobrien name. This will mean that ld -X doesn't actually strip anything. 31784865Sobrien The AIX native linker does not have a -X option, and it ignores the 31884865Sobrien -x option. */ 31984865Sobrien 320130561Sobrienbfd_boolean 32184865Sobrien_bfd_xcoff_is_local_label_name (abfd, name) 32284865Sobrien bfd *abfd ATTRIBUTE_UNUSED; 32384865Sobrien const char *name ATTRIBUTE_UNUSED; 32484865Sobrien{ 325130561Sobrien return FALSE; 32684865Sobrien} 32784865Sobrien 32884865Sobrienvoid 32984865Sobrien_bfd_xcoff_swap_sym_in (abfd, ext1, in1) 330130561Sobrien bfd *abfd; 33184865Sobrien PTR ext1; 33284865Sobrien PTR in1; 33384865Sobrien{ 33484865Sobrien SYMENT *ext = (SYMENT *)ext1; 33589857Sobrien struct internal_syment * in = (struct internal_syment *)in1; 33684865Sobrien 33784865Sobrien if (ext->e.e_name[0] != 0) 33884865Sobrien { 339130561Sobrien memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN); 34084865Sobrien } 34184865Sobrien else 34284865Sobrien { 34384865Sobrien in->_n._n_n._n_zeroes = 0; 34489857Sobrien in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset); 34584865Sobrien } 34684865Sobrien 34789857Sobrien in->n_value = H_GET_32 (abfd, ext->e_value); 34889857Sobrien in->n_scnum = H_GET_16 (abfd, ext->e_scnum); 34989857Sobrien in->n_type = H_GET_16 (abfd, ext->e_type); 35089857Sobrien in->n_sclass = H_GET_8 (abfd, ext->e_sclass); 35189857Sobrien in->n_numaux = H_GET_8 (abfd, ext->e_numaux); 35284865Sobrien} 35384865Sobrien 35484865Sobrienunsigned int 35584865Sobrien_bfd_xcoff_swap_sym_out (abfd, inp, extp) 356130561Sobrien bfd *abfd; 357130561Sobrien PTR inp; 358130561Sobrien PTR extp; 35984865Sobrien{ 36084865Sobrien struct internal_syment *in = (struct internal_syment *)inp; 36184865Sobrien SYMENT *ext =(SYMENT *)extp; 36284865Sobrien 36384865Sobrien if (in->_n._n_name[0] != 0) 36484865Sobrien { 365130561Sobrien memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN); 36684865Sobrien } 36784865Sobrien else 36884865Sobrien { 36989857Sobrien H_PUT_32 (abfd, 0, ext->e.e.e_zeroes); 37089857Sobrien H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset); 37184865Sobrien } 37284865Sobrien 37389857Sobrien H_PUT_32 (abfd, in->n_value, ext->e_value); 37489857Sobrien H_PUT_16 (abfd, in->n_scnum, ext->e_scnum); 37589857Sobrien H_PUT_16 (abfd, in->n_type, ext->e_type); 37689857Sobrien H_PUT_8 (abfd, in->n_sclass, ext->e_sclass); 37789857Sobrien H_PUT_8 (abfd, in->n_numaux, ext->e_numaux); 37884865Sobrien return bfd_coff_symesz (abfd); 37984865Sobrien} 38084865Sobrien 38184865Sobrienvoid 38284865Sobrien_bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1) 383130561Sobrien bfd *abfd; 384130561Sobrien PTR ext1; 385130561Sobrien int type; 386130561Sobrien int class; 387130561Sobrien int indx; 388130561Sobrien int numaux; 389130561Sobrien PTR in1; 39084865Sobrien{ 39189857Sobrien AUXENT * ext = (AUXENT *)ext1; 39284865Sobrien union internal_auxent *in = (union internal_auxent *)in1; 39384865Sobrien 39489857Sobrien switch (class) 39589857Sobrien { 39684865Sobrien case C_FILE: 39789857Sobrien if (ext->x_file.x_fname[0] == 0) 39889857Sobrien { 39984865Sobrien in->x_file.x_n.x_zeroes = 0; 40084865Sobrien in->x_file.x_n.x_offset = 40189857Sobrien H_GET_32 (abfd, ext->x_file.x_n.x_offset); 40289857Sobrien } 40389857Sobrien else 40489857Sobrien { 40589857Sobrien if (numaux > 1) 40689857Sobrien { 40789857Sobrien if (indx == 0) 40889857Sobrien memcpy (in->x_file.x_fname, ext->x_file.x_fname, 40989857Sobrien numaux * sizeof (AUXENT)); 41089857Sobrien } 41189857Sobrien else 41289857Sobrien { 41389857Sobrien memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); 41489857Sobrien } 41589857Sobrien } 41684865Sobrien goto end; 41784865Sobrien 41884865Sobrien /* RS/6000 "csect" auxents */ 41984865Sobrien case C_EXT: 42084865Sobrien case C_HIDEXT: 42184865Sobrien if (indx + 1 == numaux) 42284865Sobrien { 42389857Sobrien in->x_csect.x_scnlen.l = H_GET_32 (abfd, ext->x_csect.x_scnlen); 42489857Sobrien in->x_csect.x_parmhash = H_GET_32 (abfd, ext->x_csect.x_parmhash); 42589857Sobrien in->x_csect.x_snhash = H_GET_16 (abfd, ext->x_csect.x_snhash); 42684865Sobrien /* We don't have to hack bitfields in x_smtyp because it's 42784865Sobrien defined by shifts-and-ands, which are equivalent on all 42884865Sobrien byte orders. */ 42989857Sobrien in->x_csect.x_smtyp = H_GET_8 (abfd, ext->x_csect.x_smtyp); 43089857Sobrien in->x_csect.x_smclas = H_GET_8 (abfd, ext->x_csect.x_smclas); 43189857Sobrien in->x_csect.x_stab = H_GET_32 (abfd, ext->x_csect.x_stab); 43289857Sobrien in->x_csect.x_snstab = H_GET_16 (abfd, ext->x_csect.x_snstab); 43384865Sobrien goto end; 43484865Sobrien } 43584865Sobrien break; 43684865Sobrien 43784865Sobrien case C_STAT: 43884865Sobrien case C_LEAFSTAT: 43984865Sobrien case C_HIDDEN: 44089857Sobrien if (type == T_NULL) 44189857Sobrien { 44289857Sobrien in->x_scn.x_scnlen = H_GET_32 (abfd, ext->x_scn.x_scnlen); 44389857Sobrien in->x_scn.x_nreloc = H_GET_16 (abfd, ext->x_scn.x_nreloc); 44489857Sobrien in->x_scn.x_nlinno = H_GET_16 (abfd, ext->x_scn.x_nlinno); 44584865Sobrien /* PE defines some extra fields; we zero them out for 446130561Sobrien safety. */ 44784865Sobrien in->x_scn.x_checksum = 0; 44884865Sobrien in->x_scn.x_associated = 0; 44984865Sobrien in->x_scn.x_comdat = 0; 45084865Sobrien 45184865Sobrien goto end; 45284865Sobrien } 45384865Sobrien break; 45484865Sobrien } 45584865Sobrien 45689857Sobrien in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx); 45789857Sobrien in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx); 45884865Sobrien 45984865Sobrien if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class)) 46084865Sobrien { 46189857Sobrien in->x_sym.x_fcnary.x_fcn.x_lnnoptr = 46289857Sobrien H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr); 46389857Sobrien in->x_sym.x_fcnary.x_fcn.x_endndx.l = 46489857Sobrien H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx); 46584865Sobrien } 46684865Sobrien else 46784865Sobrien { 46884865Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[0] = 46989857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 47084865Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[1] = 47189857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 47284865Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[2] = 47389857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 47484865Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[3] = 47589857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 47684865Sobrien } 47784865Sobrien 47889857Sobrien if (ISFCN (type)) 47989857Sobrien { 48089857Sobrien in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize); 48189857Sobrien } 48289857Sobrien else 48389857Sobrien { 48489857Sobrien in->x_sym.x_misc.x_lnsz.x_lnno = 48589857Sobrien H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_lnno); 48689857Sobrien in->x_sym.x_misc.x_lnsz.x_size = 48789857Sobrien H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size); 48889857Sobrien } 48989857Sobrien 49089857Sobrien end: ; 49189857Sobrien /* The semicolon is because MSVC doesn't like labels at 49284865Sobrien end of block. */ 49384865Sobrien} 49484865Sobrien 49589857Sobrien 496130561Sobrienunsigned int _bfd_xcoff_swap_aux_out 497130561Sobrien PARAMS ((bfd *, PTR, int, int, int, int, PTR)); 49889857Sobrien 49984865Sobrienunsigned int 50084865Sobrien_bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp) 50189857Sobrien bfd * abfd; 50289857Sobrien PTR inp; 50384865Sobrien int type; 50484865Sobrien int class; 50584865Sobrien int indx ATTRIBUTE_UNUSED; 50684865Sobrien int numaux ATTRIBUTE_UNUSED; 50789857Sobrien PTR extp; 50884865Sobrien{ 50984865Sobrien union internal_auxent *in = (union internal_auxent *)inp; 51084865Sobrien AUXENT *ext = (AUXENT *)extp; 51184865Sobrien 512130561Sobrien memset ((PTR)ext, 0, bfd_coff_auxesz (abfd)); 51384865Sobrien switch (class) 51484865Sobrien { 51589857Sobrien case C_FILE: 51689857Sobrien if (in->x_file.x_fname[0] == 0) 51789857Sobrien { 51889857Sobrien H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes); 51989857Sobrien H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset); 52089857Sobrien } 52189857Sobrien else 52289857Sobrien { 52389857Sobrien memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN); 52489857Sobrien } 52589857Sobrien goto end; 52684865Sobrien 52789857Sobrien /* RS/6000 "csect" auxents */ 52889857Sobrien case C_EXT: 52989857Sobrien case C_HIDEXT: 53089857Sobrien if (indx + 1 == numaux) 53189857Sobrien { 53289857Sobrien H_PUT_32 (abfd, in->x_csect.x_scnlen.l, ext->x_csect.x_scnlen); 53389857Sobrien H_PUT_32 (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash); 53489857Sobrien H_PUT_16 (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash); 53589857Sobrien /* We don't have to hack bitfields in x_smtyp because it's 53689857Sobrien defined by shifts-and-ands, which are equivalent on all 53789857Sobrien byte orders. */ 53889857Sobrien H_PUT_8 (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp); 53989857Sobrien H_PUT_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas); 54089857Sobrien H_PUT_32 (abfd, in->x_csect.x_stab, ext->x_csect.x_stab); 54189857Sobrien H_PUT_16 (abfd, in->x_csect.x_snstab, ext->x_csect.x_snstab); 54289857Sobrien goto end; 54389857Sobrien } 54489857Sobrien break; 54584865Sobrien 54689857Sobrien case C_STAT: 54789857Sobrien case C_LEAFSTAT: 54889857Sobrien case C_HIDDEN: 54989857Sobrien if (type == T_NULL) 55089857Sobrien { 55189857Sobrien H_PUT_32 (abfd, in->x_scn.x_scnlen, ext->x_scn.x_scnlen); 55289857Sobrien H_PUT_16 (abfd, in->x_scn.x_nreloc, ext->x_scn.x_nreloc); 55389857Sobrien H_PUT_16 (abfd, in->x_scn.x_nlinno, ext->x_scn.x_nlinno); 55489857Sobrien goto end; 55589857Sobrien } 55689857Sobrien break; 55784865Sobrien } 55884865Sobrien 55989857Sobrien H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx); 56089857Sobrien H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx); 56184865Sobrien 56284865Sobrien if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class)) 56384865Sobrien { 56489857Sobrien H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, 56589857Sobrien ext->x_sym.x_fcnary.x_fcn.x_lnnoptr); 56689857Sobrien H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, 56789857Sobrien ext->x_sym.x_fcnary.x_fcn.x_endndx); 56884865Sobrien } 56984865Sobrien else 57084865Sobrien { 57189857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0], 57289857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 57389857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1], 57489857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 57589857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2], 57689857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 57789857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3], 57889857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 57984865Sobrien } 58084865Sobrien 58184865Sobrien if (ISFCN (type)) 58289857Sobrien H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize); 58384865Sobrien else 58484865Sobrien { 58589857Sobrien H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, 58689857Sobrien ext->x_sym.x_misc.x_lnsz.x_lnno); 58789857Sobrien H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_size, 58889857Sobrien ext->x_sym.x_misc.x_lnsz.x_size); 58984865Sobrien } 59084865Sobrien 59184865Sobrienend: 59284865Sobrien return bfd_coff_auxesz (abfd); 59384865Sobrien} 59489857Sobrien 59589857Sobrien 59684865Sobrien 59784865Sobrien/* The XCOFF reloc table. Actually, XCOFF relocations specify the 59884865Sobrien bitsize and whether they are signed or not, along with a 59984865Sobrien conventional type. This table is for the types, which are used for 60084865Sobrien different algorithms for putting in the reloc. Many of these 60184865Sobrien relocs need special_function entries, which I have not written. */ 60284865Sobrien 60384865Sobrien 60484865Sobrienreloc_howto_type xcoff_howto_table[] = 60584865Sobrien{ 60684865Sobrien /* Standard 32 bit relocation. */ 607130561Sobrien HOWTO (R_POS, /* type */ 608130561Sobrien 0, /* rightshift */ 609130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 610130561Sobrien 32, /* bitsize */ 611130561Sobrien FALSE, /* pc_relative */ 612130561Sobrien 0, /* bitpos */ 61384865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 614130561Sobrien 0, /* special_function */ 615130561Sobrien "R_POS", /* name */ 616130561Sobrien TRUE, /* partial_inplace */ 617130561Sobrien 0xffffffff, /* src_mask */ 618130561Sobrien 0xffffffff, /* dst_mask */ 619130561Sobrien FALSE), /* pcrel_offset */ 62084865Sobrien 62184865Sobrien /* 32 bit relocation, but store negative value. */ 622130561Sobrien HOWTO (R_NEG, /* type */ 623130561Sobrien 0, /* rightshift */ 624130561Sobrien -2, /* size (0 = byte, 1 = short, 2 = long) */ 625130561Sobrien 32, /* bitsize */ 626130561Sobrien FALSE, /* pc_relative */ 627130561Sobrien 0, /* bitpos */ 62884865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 629130561Sobrien 0, /* special_function */ 630130561Sobrien "R_NEG", /* name */ 631130561Sobrien TRUE, /* partial_inplace */ 632130561Sobrien 0xffffffff, /* src_mask */ 633130561Sobrien 0xffffffff, /* dst_mask */ 634130561Sobrien FALSE), /* pcrel_offset */ 63584865Sobrien 63684865Sobrien /* 32 bit PC relative relocation. */ 637130561Sobrien HOWTO (R_REL, /* type */ 638130561Sobrien 0, /* rightshift */ 639130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 640130561Sobrien 32, /* bitsize */ 641130561Sobrien TRUE, /* pc_relative */ 642130561Sobrien 0, /* bitpos */ 64384865Sobrien complain_overflow_signed, /* complain_on_overflow */ 644130561Sobrien 0, /* special_function */ 645130561Sobrien "R_REL", /* name */ 646130561Sobrien TRUE, /* partial_inplace */ 647130561Sobrien 0xffffffff, /* src_mask */ 648130561Sobrien 0xffffffff, /* dst_mask */ 649130561Sobrien FALSE), /* pcrel_offset */ 65084865Sobrien 65184865Sobrien /* 16 bit TOC relative relocation. */ 652130561Sobrien HOWTO (R_TOC, /* type */ 653130561Sobrien 0, /* rightshift */ 654130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 655130561Sobrien 16, /* bitsize */ 656130561Sobrien FALSE, /* pc_relative */ 657130561Sobrien 0, /* bitpos */ 65884865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 659130561Sobrien 0, /* special_function */ 660130561Sobrien "R_TOC", /* name */ 661130561Sobrien TRUE, /* partial_inplace */ 662130561Sobrien 0xffff, /* src_mask */ 663130561Sobrien 0xffff, /* dst_mask */ 664130561Sobrien FALSE), /* pcrel_offset */ 66584865Sobrien 66684865Sobrien /* I don't really know what this is. */ 667130561Sobrien HOWTO (R_RTB, /* type */ 668130561Sobrien 1, /* rightshift */ 669130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 670130561Sobrien 32, /* bitsize */ 671130561Sobrien FALSE, /* pc_relative */ 672130561Sobrien 0, /* bitpos */ 67384865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 674130561Sobrien 0, /* special_function */ 675130561Sobrien "R_RTB", /* name */ 676130561Sobrien TRUE, /* partial_inplace */ 677130561Sobrien 0xffffffff, /* src_mask */ 678130561Sobrien 0xffffffff, /* dst_mask */ 679130561Sobrien FALSE), /* pcrel_offset */ 68084865Sobrien 68184865Sobrien /* External TOC relative symbol. */ 682130561Sobrien HOWTO (R_GL, /* type */ 683130561Sobrien 0, /* rightshift */ 684104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 685130561Sobrien 16, /* bitsize */ 686130561Sobrien FALSE, /* pc_relative */ 687130561Sobrien 0, /* bitpos */ 68884865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 689130561Sobrien 0, /* special_function */ 690130561Sobrien "R_GL", /* name */ 691130561Sobrien TRUE, /* partial_inplace */ 692130561Sobrien 0xffff, /* src_mask */ 693130561Sobrien 0xffff, /* dst_mask */ 694130561Sobrien FALSE), /* pcrel_offset */ 69584865Sobrien 696130561Sobrien /* Local TOC relative symbol. */ 697130561Sobrien HOWTO (R_TCL, /* type */ 698130561Sobrien 0, /* rightshift */ 699104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 700130561Sobrien 16, /* bitsize */ 701130561Sobrien FALSE, /* pc_relative */ 702130561Sobrien 0, /* bitpos */ 70384865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 704130561Sobrien 0, /* special_function */ 705130561Sobrien "R_TCL", /* name */ 706130561Sobrien TRUE, /* partial_inplace */ 707130561Sobrien 0xffff, /* src_mask */ 708130561Sobrien 0xffff, /* dst_mask */ 709130561Sobrien FALSE), /* pcrel_offset */ 71084865Sobrien 71184865Sobrien EMPTY_HOWTO (7), 71284865Sobrien 71384865Sobrien /* Non modifiable absolute branch. */ 714130561Sobrien HOWTO (R_BA, /* type */ 715130561Sobrien 0, /* rightshift */ 716130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 717130561Sobrien 26, /* bitsize */ 718130561Sobrien FALSE, /* pc_relative */ 719130561Sobrien 0, /* bitpos */ 72084865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 721130561Sobrien 0, /* special_function */ 722130561Sobrien "R_BA_26", /* name */ 723130561Sobrien TRUE, /* partial_inplace */ 724104834Sobrien 0x03fffffc, /* src_mask */ 725104834Sobrien 0x03fffffc, /* dst_mask */ 726130561Sobrien FALSE), /* pcrel_offset */ 72784865Sobrien 72884865Sobrien EMPTY_HOWTO (9), 72984865Sobrien 73084865Sobrien /* Non modifiable relative branch. */ 731130561Sobrien HOWTO (R_BR, /* type */ 732130561Sobrien 0, /* rightshift */ 733130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 734130561Sobrien 26, /* bitsize */ 735130561Sobrien TRUE, /* pc_relative */ 736130561Sobrien 0, /* bitpos */ 73784865Sobrien complain_overflow_signed, /* complain_on_overflow */ 738130561Sobrien 0, /* special_function */ 739130561Sobrien "R_BR", /* name */ 740130561Sobrien TRUE, /* partial_inplace */ 741130561Sobrien 0x03fffffc, /* src_mask */ 742130561Sobrien 0x03fffffc, /* dst_mask */ 743130561Sobrien FALSE), /* pcrel_offset */ 74484865Sobrien 74584865Sobrien EMPTY_HOWTO (0xb), 74684865Sobrien 74784865Sobrien /* Indirect load. */ 748130561Sobrien HOWTO (R_RL, /* type */ 749130561Sobrien 0, /* rightshift */ 750104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 751130561Sobrien 16, /* bitsize */ 752130561Sobrien FALSE, /* pc_relative */ 753130561Sobrien 0, /* bitpos */ 75484865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 755130561Sobrien 0, /* special_function */ 756130561Sobrien "R_RL", /* name */ 757130561Sobrien TRUE, /* partial_inplace */ 758130561Sobrien 0xffff, /* src_mask */ 759130561Sobrien 0xffff, /* dst_mask */ 760130561Sobrien FALSE), /* pcrel_offset */ 76184865Sobrien 76284865Sobrien /* Load address. */ 763130561Sobrien HOWTO (R_RLA, /* type */ 764130561Sobrien 0, /* rightshift */ 765104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 766130561Sobrien 16, /* bitsize */ 767130561Sobrien FALSE, /* pc_relative */ 768130561Sobrien 0, /* bitpos */ 76984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 770130561Sobrien 0, /* special_function */ 771130561Sobrien "R_RLA", /* name */ 772130561Sobrien TRUE, /* partial_inplace */ 773130561Sobrien 0xffff, /* src_mask */ 774130561Sobrien 0xffff, /* dst_mask */ 775130561Sobrien FALSE), /* pcrel_offset */ 77684865Sobrien 77784865Sobrien EMPTY_HOWTO (0xe), 77884865Sobrien 77984865Sobrien /* Non-relocating reference. */ 780130561Sobrien HOWTO (R_REF, /* type */ 781130561Sobrien 0, /* rightshift */ 782130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 783130561Sobrien 32, /* bitsize */ 784130561Sobrien FALSE, /* pc_relative */ 785130561Sobrien 0, /* bitpos */ 786104834Sobrien complain_overflow_dont, /* complain_on_overflow */ 787130561Sobrien 0, /* special_function */ 788130561Sobrien "R_REF", /* name */ 789130561Sobrien FALSE, /* partial_inplace */ 790130561Sobrien 0, /* src_mask */ 791130561Sobrien 0, /* dst_mask */ 792130561Sobrien FALSE), /* pcrel_offset */ 79384865Sobrien 79484865Sobrien EMPTY_HOWTO (0x10), 79584865Sobrien EMPTY_HOWTO (0x11), 79684865Sobrien 79784865Sobrien /* TOC relative indirect load. */ 798130561Sobrien HOWTO (R_TRL, /* type */ 799130561Sobrien 0, /* rightshift */ 800104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 801130561Sobrien 16, /* bitsize */ 802130561Sobrien FALSE, /* pc_relative */ 803130561Sobrien 0, /* bitpos */ 80484865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 805130561Sobrien 0, /* special_function */ 806130561Sobrien "R_TRL", /* name */ 807130561Sobrien TRUE, /* partial_inplace */ 808130561Sobrien 0xffff, /* src_mask */ 809130561Sobrien 0xffff, /* dst_mask */ 810130561Sobrien FALSE), /* pcrel_offset */ 81184865Sobrien 81284865Sobrien /* TOC relative load address. */ 813130561Sobrien HOWTO (R_TRLA, /* type */ 814130561Sobrien 0, /* rightshift */ 815104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 816130561Sobrien 16, /* bitsize */ 817130561Sobrien FALSE, /* pc_relative */ 818130561Sobrien 0, /* bitpos */ 81984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 820130561Sobrien 0, /* special_function */ 821130561Sobrien "R_TRLA", /* name */ 822130561Sobrien TRUE, /* partial_inplace */ 823130561Sobrien 0xffff, /* src_mask */ 824130561Sobrien 0xffff, /* dst_mask */ 825130561Sobrien FALSE), /* pcrel_offset */ 82684865Sobrien 82784865Sobrien /* Modifiable relative branch. */ 828130561Sobrien HOWTO (R_RRTBI, /* type */ 829130561Sobrien 1, /* rightshift */ 830130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 831130561Sobrien 32, /* bitsize */ 832130561Sobrien FALSE, /* pc_relative */ 833130561Sobrien 0, /* bitpos */ 83484865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 835130561Sobrien 0, /* special_function */ 836130561Sobrien "R_RRTBI", /* name */ 837130561Sobrien TRUE, /* partial_inplace */ 838130561Sobrien 0xffffffff, /* src_mask */ 839130561Sobrien 0xffffffff, /* dst_mask */ 840130561Sobrien FALSE), /* pcrel_offset */ 84184865Sobrien 84284865Sobrien /* Modifiable absolute branch. */ 843130561Sobrien HOWTO (R_RRTBA, /* type */ 844130561Sobrien 1, /* rightshift */ 845130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 846130561Sobrien 32, /* bitsize */ 847130561Sobrien FALSE, /* pc_relative */ 848130561Sobrien 0, /* bitpos */ 84984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 850130561Sobrien 0, /* special_function */ 851130561Sobrien "R_RRTBA", /* name */ 852130561Sobrien TRUE, /* partial_inplace */ 853130561Sobrien 0xffffffff, /* src_mask */ 854130561Sobrien 0xffffffff, /* dst_mask */ 855130561Sobrien FALSE), /* pcrel_offset */ 85684865Sobrien 85784865Sobrien /* Modifiable call absolute indirect. */ 858130561Sobrien HOWTO (R_CAI, /* type */ 859130561Sobrien 0, /* rightshift */ 860104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 861130561Sobrien 16, /* bitsize */ 862130561Sobrien FALSE, /* pc_relative */ 863130561Sobrien 0, /* bitpos */ 86484865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 865130561Sobrien 0, /* special_function */ 866130561Sobrien "R_CAI", /* name */ 867130561Sobrien TRUE, /* partial_inplace */ 868130561Sobrien 0xffff, /* src_mask */ 869130561Sobrien 0xffff, /* dst_mask */ 870130561Sobrien FALSE), /* pcrel_offset */ 87184865Sobrien 87284865Sobrien /* Modifiable call relative. */ 873130561Sobrien HOWTO (R_CREL, /* type */ 874130561Sobrien 0, /* rightshift */ 875104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 876130561Sobrien 16, /* bitsize */ 877130561Sobrien FALSE, /* pc_relative */ 878130561Sobrien 0, /* bitpos */ 87984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 880130561Sobrien 0, /* special_function */ 881130561Sobrien "R_CREL", /* name */ 882130561Sobrien TRUE, /* partial_inplace */ 883130561Sobrien 0xffff, /* src_mask */ 884130561Sobrien 0xffff, /* dst_mask */ 885130561Sobrien FALSE), /* pcrel_offset */ 88684865Sobrien 88784865Sobrien /* Modifiable branch absolute. */ 888130561Sobrien HOWTO (R_RBA, /* type */ 889130561Sobrien 0, /* rightshift */ 890130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 891130561Sobrien 26, /* bitsize */ 892130561Sobrien FALSE, /* pc_relative */ 893130561Sobrien 0, /* bitpos */ 89484865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 895130561Sobrien 0, /* special_function */ 896130561Sobrien "R_RBA", /* name */ 897130561Sobrien TRUE, /* partial_inplace */ 898104834Sobrien 0x03fffffc, /* src_mask */ 899104834Sobrien 0x03fffffc, /* dst_mask */ 900130561Sobrien FALSE), /* pcrel_offset */ 90184865Sobrien 90284865Sobrien /* Modifiable branch absolute. */ 903130561Sobrien HOWTO (R_RBAC, /* type */ 904130561Sobrien 0, /* rightshift */ 905130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 906130561Sobrien 32, /* bitsize */ 907130561Sobrien FALSE, /* pc_relative */ 908130561Sobrien 0, /* bitpos */ 90984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 910130561Sobrien 0, /* special_function */ 911130561Sobrien "R_RBAC", /* name */ 912130561Sobrien TRUE, /* partial_inplace */ 913104834Sobrien 0xffffffff, /* src_mask */ 914104834Sobrien 0xffffffff, /* dst_mask */ 915130561Sobrien FALSE), /* pcrel_offset */ 91684865Sobrien 91784865Sobrien /* Modifiable branch relative. */ 918130561Sobrien HOWTO (R_RBR, /* type */ 919130561Sobrien 0, /* rightshift */ 920130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 921130561Sobrien 26, /* bitsize */ 922130561Sobrien FALSE, /* pc_relative */ 923130561Sobrien 0, /* bitpos */ 92484865Sobrien complain_overflow_signed, /* complain_on_overflow */ 925130561Sobrien 0, /* special_function */ 926130561Sobrien "R_RBR_26", /* name */ 927130561Sobrien TRUE, /* partial_inplace */ 928104834Sobrien 0x03fffffc, /* src_mask */ 929104834Sobrien 0x03fffffc, /* dst_mask */ 930130561Sobrien FALSE), /* pcrel_offset */ 93184865Sobrien 93284865Sobrien /* Modifiable branch absolute. */ 933130561Sobrien HOWTO (R_RBRC, /* type */ 934130561Sobrien 0, /* rightshift */ 935104834Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 936130561Sobrien 16, /* bitsize */ 937130561Sobrien FALSE, /* pc_relative */ 938130561Sobrien 0, /* bitpos */ 93984865Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 940130561Sobrien 0, /* special_function */ 941130561Sobrien "R_RBRC", /* name */ 942130561Sobrien TRUE, /* partial_inplace */ 943130561Sobrien 0xffff, /* src_mask */ 944130561Sobrien 0xffff, /* dst_mask */ 945130561Sobrien FALSE), /* pcrel_offset */ 94689857Sobrien 947104834Sobrien /* 16 bit Non modifiable absolute branch. */ 948130561Sobrien HOWTO (R_BA, /* type */ 949130561Sobrien 0, /* rightshift */ 950130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 951130561Sobrien 16, /* bitsize */ 952130561Sobrien FALSE, /* pc_relative */ 953130561Sobrien 0, /* bitpos */ 954104834Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 955130561Sobrien 0, /* special_function */ 956130561Sobrien "R_BA_16", /* name */ 957130561Sobrien TRUE, /* partial_inplace */ 958130561Sobrien 0xfffc, /* src_mask */ 959130561Sobrien 0xfffc, /* dst_mask */ 960130561Sobrien FALSE), /* pcrel_offset */ 96184865Sobrien 962104834Sobrien /* Modifiable branch relative. */ 963130561Sobrien HOWTO (R_RBR, /* type */ 964130561Sobrien 0, /* rightshift */ 965130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 966130561Sobrien 16, /* bitsize */ 967130561Sobrien FALSE, /* pc_relative */ 968130561Sobrien 0, /* bitpos */ 969104834Sobrien complain_overflow_signed, /* complain_on_overflow */ 970130561Sobrien 0, /* special_function */ 971130561Sobrien "R_RBR_16", /* name */ 972130561Sobrien TRUE, /* partial_inplace */ 973130561Sobrien 0xffff, /* src_mask */ 974130561Sobrien 0xffff, /* dst_mask */ 975130561Sobrien FALSE), /* pcrel_offset */ 976104834Sobrien 977104834Sobrien /* Modifiable branch relative. */ 978130561Sobrien HOWTO (R_RBA, /* type */ 979130561Sobrien 0, /* rightshift */ 980130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 981130561Sobrien 16, /* bitsize */ 982130561Sobrien FALSE, /* pc_relative */ 983130561Sobrien 0, /* bitpos */ 984104834Sobrien complain_overflow_signed, /* complain_on_overflow */ 985130561Sobrien 0, /* special_function */ 986130561Sobrien "R_RBA_16", /* name */ 987130561Sobrien TRUE, /* partial_inplace */ 988130561Sobrien 0xffff, /* src_mask */ 989130561Sobrien 0xffff, /* dst_mask */ 990130561Sobrien FALSE), /* pcrel_offset */ 991104834Sobrien 99284865Sobrien}; 99384865Sobrien 99484865Sobrienvoid 995104834Sobrienxcoff_rtype2howto (relent, internal) 99684865Sobrien arelent *relent; 99784865Sobrien struct internal_reloc *internal; 99884865Sobrien{ 999104834Sobrien if (internal->r_type > R_RBRC) 100089857Sobrien abort (); 100184865Sobrien 1002104834Sobrien /* Default howto layout works most of the time */ 1003104834Sobrien relent->howto = &xcoff_howto_table[internal->r_type]; 1004130561Sobrien 1005130561Sobrien /* Special case some 16 bit reloc */ 1006104834Sobrien if (15 == (internal->r_size & 0x1f)) 1007104834Sobrien { 1008130561Sobrien if (R_BA == internal->r_type) 1009104834Sobrien relent->howto = &xcoff_howto_table[0x1c]; 1010130561Sobrien else if (R_RBR == internal->r_type) 1011104834Sobrien relent->howto = &xcoff_howto_table[0x1d]; 1012130561Sobrien else if (R_RBA == internal->r_type) 1013104834Sobrien relent->howto = &xcoff_howto_table[0x1e]; 1014104834Sobrien } 1015130561Sobrien 101684865Sobrien /* The r_size field of an XCOFF reloc encodes the bitsize of the 101784865Sobrien relocation, as well as indicating whether it is signed or not. 101884865Sobrien Doublecheck that the relocation information gathered from the 101984865Sobrien type matches this information. The bitsize is not significant 102084865Sobrien for R_REF relocs. */ 102184865Sobrien if (relent->howto->dst_mask != 0 102284865Sobrien && (relent->howto->bitsize 1023104834Sobrien != ((unsigned int) internal->r_size & 0x1f) + 1)) 102484865Sobrien abort (); 102584865Sobrien} 102684865Sobrien 102784865Sobrienreloc_howto_type * 102884865Sobrien_bfd_xcoff_reloc_type_lookup (abfd, code) 102984865Sobrien bfd *abfd ATTRIBUTE_UNUSED; 103084865Sobrien bfd_reloc_code_real_type code; 103184865Sobrien{ 103284865Sobrien switch (code) 103384865Sobrien { 103484865Sobrien case BFD_RELOC_PPC_B26: 103584865Sobrien return &xcoff_howto_table[0xa]; 1036104834Sobrien case BFD_RELOC_PPC_BA16: 1037104834Sobrien return &xcoff_howto_table[0x1c]; 103884865Sobrien case BFD_RELOC_PPC_BA26: 103984865Sobrien return &xcoff_howto_table[8]; 104084865Sobrien case BFD_RELOC_PPC_TOC16: 104184865Sobrien return &xcoff_howto_table[3]; 104284865Sobrien case BFD_RELOC_32: 104384865Sobrien case BFD_RELOC_CTOR: 104484865Sobrien return &xcoff_howto_table[0]; 104584865Sobrien default: 104684865Sobrien return NULL; 104784865Sobrien } 104884865Sobrien} 104989857Sobrien 1050218822Sdimstatic reloc_howto_type * 1051218822Sdim_bfd_xcoff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1052218822Sdim const char *r_name) 1053218822Sdim{ 1054218822Sdim unsigned int i; 1055218822Sdim 1056218822Sdim for (i = 0; 1057218822Sdim i < sizeof (xcoff_howto_table) / sizeof (xcoff_howto_table[0]); 1058218822Sdim i++) 1059218822Sdim if (xcoff_howto_table[i].name != NULL 1060218822Sdim && strcasecmp (xcoff_howto_table[i].name, r_name) == 0) 1061218822Sdim return &xcoff_howto_table[i]; 1062218822Sdim 1063218822Sdim return NULL; 1064218822Sdim} 106584865Sobrien 106684865Sobrien/* XCOFF archive support. The original version of this code was by 106784865Sobrien Damon A. Permezel. It was enhanced to permit cross support, and 106884865Sobrien writing archive files, by Ian Lance Taylor, Cygnus Support. 106984865Sobrien 107084865Sobrien XCOFF uses its own archive format. Everything is hooked together 107184865Sobrien with file offset links, so it is possible to rapidly update an 107284865Sobrien archive in place. Of course, we don't do that. An XCOFF archive 107384865Sobrien has a real file header, not just an ARMAG string. The structure of 107484865Sobrien the file header and of each archive header appear below. 107584865Sobrien 107684865Sobrien An XCOFF archive also has a member table, which is a list of 107784865Sobrien elements in the archive (you can get that by looking through the 107884865Sobrien linked list, but you have to read a lot more of the file). The 107984865Sobrien member table has a normal archive header with an empty name. It is 108084865Sobrien normally (and perhaps must be) the second to last entry in the 108184865Sobrien archive. The member table data is almost printable ASCII. It 108284865Sobrien starts with a 12 character decimal string which is the number of 108384865Sobrien entries in the table. For each entry it has a 12 character decimal 108484865Sobrien string which is the offset in the archive of that member. These 108584865Sobrien entries are followed by a series of null terminated strings which 108684865Sobrien are the member names for each entry. 108784865Sobrien 108884865Sobrien Finally, an XCOFF archive has a global symbol table, which is what 108984865Sobrien we call the armap. The global symbol table has a normal archive 109084865Sobrien header with an empty name. It is normally (and perhaps must be) 109184865Sobrien the last entry in the archive. The contents start with a four byte 109284865Sobrien binary number which is the number of entries. This is followed by 109384865Sobrien a that many four byte binary numbers; each is the file offset of an 109484865Sobrien entry in the archive. These numbers are followed by a series of 109584865Sobrien null terminated strings, which are symbol names. 109684865Sobrien 109784865Sobrien AIX 4.3 introduced a new archive format which can handle larger 109884865Sobrien files and also 32- and 64-bit objects in the same archive. The 109984865Sobrien things said above remain true except that there is now more than 110084865Sobrien one global symbol table. The one is used to index 32-bit objects, 110184865Sobrien the other for 64-bit objects. 110284865Sobrien 110384865Sobrien The new archives (recognizable by the new ARMAG string) has larger 110484865Sobrien field lengths so that we cannot really share any code. Also we have 110584865Sobrien to take care that we are not generating the new form of archives 110684865Sobrien on AIX 4.2 or earlier systems. */ 110784865Sobrien 110884865Sobrien/* XCOFF archives use this as a magic string. Note that both strings 110984865Sobrien have the same length. */ 111084865Sobrien 1111104834Sobrien/* Set the magic for archive. */ 111284865Sobrien 1113130561Sobrienbfd_boolean 1114104834Sobrienbfd_xcoff_ar_archive_set_magic (abfd, magic) 1115104834Sobrien bfd *abfd ATTRIBUTE_UNUSED; 1116104834Sobrien char *magic ATTRIBUTE_UNUSED; 1117104834Sobrien{ 1118104834Sobrien /* Not supported yet. */ 1119130561Sobrien return FALSE; 1120104834Sobrien /* bfd_xcoff_archive_set_magic (abfd, magic); */ 1121104834Sobrien} 112284865Sobrien 112384865Sobrien/* Read in the armap of an XCOFF archive. */ 112484865Sobrien 1125130561Sobrienbfd_boolean 112684865Sobrien_bfd_xcoff_slurp_armap (abfd) 112784865Sobrien bfd *abfd; 112884865Sobrien{ 112984865Sobrien file_ptr off; 113084865Sobrien size_t namlen; 113184865Sobrien bfd_size_type sz; 113284865Sobrien bfd_byte *contents, *cend; 113384865Sobrien bfd_vma c, i; 113484865Sobrien carsym *arsym; 113584865Sobrien bfd_byte *p; 113684865Sobrien 113784865Sobrien if (xcoff_ardata (abfd) == NULL) 113884865Sobrien { 1139130561Sobrien bfd_has_map (abfd) = FALSE; 1140130561Sobrien return TRUE; 114184865Sobrien } 114284865Sobrien 114384865Sobrien if (! xcoff_big_format_p (abfd)) 114484865Sobrien { 114584865Sobrien /* This is for the old format. */ 114684865Sobrien struct xcoff_ar_hdr hdr; 114784865Sobrien 114884865Sobrien off = strtol (xcoff_ardata (abfd)->symoff, (char **) NULL, 10); 114984865Sobrien if (off == 0) 115084865Sobrien { 1151130561Sobrien bfd_has_map (abfd) = FALSE; 1152130561Sobrien return TRUE; 115384865Sobrien } 115484865Sobrien 115584865Sobrien if (bfd_seek (abfd, off, SEEK_SET) != 0) 1156130561Sobrien return FALSE; 115784865Sobrien 115884865Sobrien /* The symbol table starts with a normal archive header. */ 115989857Sobrien if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd) 116089857Sobrien != SIZEOF_AR_HDR) 1161130561Sobrien return FALSE; 116284865Sobrien 116384865Sobrien /* Skip the name (normally empty). */ 116484865Sobrien namlen = strtol (hdr.namlen, (char **) NULL, 10); 116589857Sobrien off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG; 116689857Sobrien if (bfd_seek (abfd, off, SEEK_CUR) != 0) 1167130561Sobrien return FALSE; 116884865Sobrien 116984865Sobrien sz = strtol (hdr.size, (char **) NULL, 10); 117084865Sobrien 117184865Sobrien /* Read in the entire symbol table. */ 117284865Sobrien contents = (bfd_byte *) bfd_alloc (abfd, sz); 117384865Sobrien if (contents == NULL) 1174130561Sobrien return FALSE; 117589857Sobrien if (bfd_bread ((PTR) contents, sz, abfd) != sz) 1176130561Sobrien return FALSE; 117784865Sobrien 117884865Sobrien /* The symbol table starts with a four byte count. */ 117989857Sobrien c = H_GET_32 (abfd, contents); 118084865Sobrien 118184865Sobrien if (c * 4 >= sz) 118284865Sobrien { 118384865Sobrien bfd_set_error (bfd_error_bad_value); 1184130561Sobrien return FALSE; 118584865Sobrien } 118684865Sobrien 118789857Sobrien bfd_ardata (abfd)->symdefs = 118889857Sobrien ((carsym *) bfd_alloc (abfd, c * sizeof (carsym))); 118984865Sobrien if (bfd_ardata (abfd)->symdefs == NULL) 1190130561Sobrien return FALSE; 119184865Sobrien 119284865Sobrien /* After the count comes a list of four byte file offsets. */ 119384865Sobrien for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 4; 119484865Sobrien i < c; 119584865Sobrien ++i, ++arsym, p += 4) 119689857Sobrien arsym->file_offset = H_GET_32 (abfd, p); 119784865Sobrien } 119884865Sobrien else 119984865Sobrien { 120084865Sobrien /* This is for the new format. */ 120184865Sobrien struct xcoff_ar_hdr_big hdr; 120284865Sobrien 120384865Sobrien off = strtol (xcoff_ardata_big (abfd)->symoff, (char **) NULL, 10); 120484865Sobrien if (off == 0) 120584865Sobrien { 1206130561Sobrien bfd_has_map (abfd) = FALSE; 1207130561Sobrien return TRUE; 120884865Sobrien } 120984865Sobrien 121084865Sobrien if (bfd_seek (abfd, off, SEEK_SET) != 0) 1211130561Sobrien return FALSE; 121284865Sobrien 121384865Sobrien /* The symbol table starts with a normal archive header. */ 121489857Sobrien if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd) 121584865Sobrien != SIZEOF_AR_HDR_BIG) 1216130561Sobrien return FALSE; 121784865Sobrien 121884865Sobrien /* Skip the name (normally empty). */ 121984865Sobrien namlen = strtol (hdr.namlen, (char **) NULL, 10); 122089857Sobrien off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG; 122189857Sobrien if (bfd_seek (abfd, off, SEEK_CUR) != 0) 1222130561Sobrien return FALSE; 122384865Sobrien 122484865Sobrien /* XXX This actually has to be a call to strtoll (at least on 32-bit 122584865Sobrien machines) since the field width is 20 and there numbers with more 122684865Sobrien than 32 bits can be represented. */ 122784865Sobrien sz = strtol (hdr.size, (char **) NULL, 10); 122884865Sobrien 122984865Sobrien /* Read in the entire symbol table. */ 123084865Sobrien contents = (bfd_byte *) bfd_alloc (abfd, sz); 123184865Sobrien if (contents == NULL) 1232130561Sobrien return FALSE; 123389857Sobrien if (bfd_bread ((PTR) contents, sz, abfd) != sz) 1234130561Sobrien return FALSE; 123584865Sobrien 123684865Sobrien /* The symbol table starts with an eight byte count. */ 123789857Sobrien c = H_GET_64 (abfd, contents); 123884865Sobrien 123984865Sobrien if (c * 8 >= sz) 124084865Sobrien { 124184865Sobrien bfd_set_error (bfd_error_bad_value); 1242130561Sobrien return FALSE; 124384865Sobrien } 124484865Sobrien 124589857Sobrien bfd_ardata (abfd)->symdefs = 124689857Sobrien ((carsym *) bfd_alloc (abfd, c * sizeof (carsym))); 124784865Sobrien if (bfd_ardata (abfd)->symdefs == NULL) 1248130561Sobrien return FALSE; 124984865Sobrien 125084865Sobrien /* After the count comes a list of eight byte file offsets. */ 125184865Sobrien for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8; 125284865Sobrien i < c; 125384865Sobrien ++i, ++arsym, p += 8) 125489857Sobrien arsym->file_offset = H_GET_64 (abfd, p); 125584865Sobrien } 125684865Sobrien 125784865Sobrien /* After the file offsets come null terminated symbol names. */ 125884865Sobrien cend = contents + sz; 125984865Sobrien for (i = 0, arsym = bfd_ardata (abfd)->symdefs; 126084865Sobrien i < c; 126184865Sobrien ++i, ++arsym, p += strlen ((char *) p) + 1) 126284865Sobrien { 126384865Sobrien if (p >= cend) 126484865Sobrien { 126584865Sobrien bfd_set_error (bfd_error_bad_value); 1266130561Sobrien return FALSE; 126784865Sobrien } 126884865Sobrien arsym->name = (char *) p; 126984865Sobrien } 127084865Sobrien 127184865Sobrien bfd_ardata (abfd)->symdef_count = c; 1272130561Sobrien bfd_has_map (abfd) = TRUE; 127384865Sobrien 1274130561Sobrien return TRUE; 127584865Sobrien} 127684865Sobrien 127784865Sobrien/* See if this is an XCOFF archive. */ 127884865Sobrien 127984865Sobrienconst bfd_target * 128084865Sobrien_bfd_xcoff_archive_p (abfd) 128184865Sobrien bfd *abfd; 128284865Sobrien{ 1283104834Sobrien struct artdata *tdata_hold; 128484865Sobrien char magic[SXCOFFARMAG]; 1285104834Sobrien bfd_size_type amt = SXCOFFARMAG; 128684865Sobrien 1287104834Sobrien if (bfd_bread ((PTR) magic, amt, abfd) != amt) 128884865Sobrien { 128984865Sobrien if (bfd_get_error () != bfd_error_system_call) 129084865Sobrien bfd_set_error (bfd_error_wrong_format); 129184865Sobrien return NULL; 129284865Sobrien } 129384865Sobrien 129484865Sobrien if (strncmp (magic, XCOFFARMAG, SXCOFFARMAG) != 0 129584865Sobrien && strncmp (magic, XCOFFARMAGBIG, SXCOFFARMAG) != 0) 129684865Sobrien { 129784865Sobrien bfd_set_error (bfd_error_wrong_format); 129884865Sobrien return NULL; 129984865Sobrien } 130084865Sobrien 1301104834Sobrien tdata_hold = bfd_ardata (abfd); 1302104834Sobrien 130389857Sobrien amt = sizeof (struct artdata); 1304104834Sobrien bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt); 130584865Sobrien if (bfd_ardata (abfd) == (struct artdata *) NULL) 1306104834Sobrien goto error_ret_restore; 130784865Sobrien 1308218822Sdim /* Cleared by bfd_zalloc above. 1309218822Sdim bfd_ardata (abfd)->cache = NULL; 1310218822Sdim bfd_ardata (abfd)->archive_head = NULL; 1311218822Sdim bfd_ardata (abfd)->symdefs = NULL; 1312218822Sdim bfd_ardata (abfd)->extended_names = NULL; 1313218822Sdim bfd_ardata (abfd)->extended_names_size = 0; */ 131484865Sobrien 131584865Sobrien /* Now handle the two formats. */ 131684865Sobrien if (magic[1] != 'b') 131784865Sobrien { 131884865Sobrien /* This is the old format. */ 131984865Sobrien struct xcoff_ar_file_hdr hdr; 132084865Sobrien 132184865Sobrien /* Copy over the magic string. */ 132284865Sobrien memcpy (hdr.magic, magic, SXCOFFARMAG); 132384865Sobrien 132484865Sobrien /* Now read the rest of the file header. */ 1325104834Sobrien amt = SIZEOF_AR_FILE_HDR - SXCOFFARMAG; 1326104834Sobrien if (bfd_bread ((PTR) &hdr.memoff, amt, abfd) != amt) 132784865Sobrien { 132884865Sobrien if (bfd_get_error () != bfd_error_system_call) 132984865Sobrien bfd_set_error (bfd_error_wrong_format); 1330104834Sobrien goto error_ret; 133184865Sobrien } 133284865Sobrien 133384865Sobrien bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff, 133484865Sobrien (char **) NULL, 10); 133584865Sobrien 133689857Sobrien amt = SIZEOF_AR_FILE_HDR; 133789857Sobrien bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt); 133884865Sobrien if (bfd_ardata (abfd)->tdata == NULL) 1339104834Sobrien goto error_ret; 134084865Sobrien 134184865Sobrien memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR); 134284865Sobrien } 134384865Sobrien else 134484865Sobrien { 134584865Sobrien /* This is the new format. */ 134684865Sobrien struct xcoff_ar_file_hdr_big hdr; 134784865Sobrien 134884865Sobrien /* Copy over the magic string. */ 134984865Sobrien memcpy (hdr.magic, magic, SXCOFFARMAG); 135084865Sobrien 135184865Sobrien /* Now read the rest of the file header. */ 1352104834Sobrien amt = SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG; 1353104834Sobrien if (bfd_bread ((PTR) &hdr.memoff, amt, abfd) != amt) 135484865Sobrien { 135584865Sobrien if (bfd_get_error () != bfd_error_system_call) 135684865Sobrien bfd_set_error (bfd_error_wrong_format); 1357104834Sobrien goto error_ret; 135884865Sobrien } 135984865Sobrien 1360104834Sobrien bfd_ardata (abfd)->first_file_filepos = bfd_scan_vma (hdr.firstmemoff, 1361104834Sobrien (const char **) 0, 1362104834Sobrien 10); 136384865Sobrien 136489857Sobrien amt = SIZEOF_AR_FILE_HDR_BIG; 136589857Sobrien bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt); 136684865Sobrien if (bfd_ardata (abfd)->tdata == NULL) 1367104834Sobrien goto error_ret; 136884865Sobrien 136984865Sobrien memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG); 137084865Sobrien } 137184865Sobrien 137284865Sobrien if (! _bfd_xcoff_slurp_armap (abfd)) 137384865Sobrien { 1374104834Sobrien error_ret: 137584865Sobrien bfd_release (abfd, bfd_ardata (abfd)); 1376104834Sobrien error_ret_restore: 1377104834Sobrien bfd_ardata (abfd) = tdata_hold; 137884865Sobrien return NULL; 137984865Sobrien } 138084865Sobrien 138184865Sobrien return abfd->xvec; 138284865Sobrien} 138384865Sobrien 138484865Sobrien/* Read the archive header in an XCOFF archive. */ 138584865Sobrien 138684865SobrienPTR 138784865Sobrien_bfd_xcoff_read_ar_hdr (abfd) 138884865Sobrien bfd *abfd; 138984865Sobrien{ 139089857Sobrien bfd_size_type namlen; 139184865Sobrien struct areltdata *ret; 139289857Sobrien bfd_size_type amt = sizeof (struct areltdata); 139384865Sobrien 139489857Sobrien ret = (struct areltdata *) bfd_alloc (abfd, amt); 139584865Sobrien if (ret == NULL) 139684865Sobrien return NULL; 139784865Sobrien 139884865Sobrien if (! xcoff_big_format_p (abfd)) 139984865Sobrien { 140084865Sobrien struct xcoff_ar_hdr hdr; 140184865Sobrien struct xcoff_ar_hdr *hdrp; 140284865Sobrien 140389857Sobrien if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd) 140489857Sobrien != SIZEOF_AR_HDR) 140584865Sobrien { 140684865Sobrien free (ret); 140784865Sobrien return NULL; 140884865Sobrien } 140984865Sobrien 141084865Sobrien namlen = strtol (hdr.namlen, (char **) NULL, 10); 141189857Sobrien amt = SIZEOF_AR_HDR + namlen + 1; 141289857Sobrien hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd, amt); 141384865Sobrien if (hdrp == NULL) 141484865Sobrien { 141584865Sobrien free (ret); 141684865Sobrien return NULL; 141784865Sobrien } 141884865Sobrien memcpy (hdrp, &hdr, SIZEOF_AR_HDR); 141989857Sobrien if (bfd_bread ((char *) hdrp + SIZEOF_AR_HDR, namlen, abfd) != namlen) 142084865Sobrien { 142184865Sobrien free (ret); 142284865Sobrien return NULL; 142384865Sobrien } 142484865Sobrien ((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0'; 142584865Sobrien 142684865Sobrien ret->arch_header = (char *) hdrp; 142784865Sobrien ret->parsed_size = strtol (hdr.size, (char **) NULL, 10); 142884865Sobrien ret->filename = (char *) hdrp + SIZEOF_AR_HDR; 142984865Sobrien } 143084865Sobrien else 143184865Sobrien { 143284865Sobrien struct xcoff_ar_hdr_big hdr; 143384865Sobrien struct xcoff_ar_hdr_big *hdrp; 143484865Sobrien 143589857Sobrien if (bfd_bread ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd) 143684865Sobrien != SIZEOF_AR_HDR_BIG) 143784865Sobrien { 143884865Sobrien free (ret); 143984865Sobrien return NULL; 144084865Sobrien } 144184865Sobrien 144284865Sobrien namlen = strtol (hdr.namlen, (char **) NULL, 10); 144389857Sobrien amt = SIZEOF_AR_HDR_BIG + namlen + 1; 144489857Sobrien hdrp = (struct xcoff_ar_hdr_big *) bfd_alloc (abfd, amt); 144584865Sobrien if (hdrp == NULL) 144684865Sobrien { 144784865Sobrien free (ret); 144884865Sobrien return NULL; 144984865Sobrien } 145084865Sobrien memcpy (hdrp, &hdr, SIZEOF_AR_HDR_BIG); 145189857Sobrien if (bfd_bread ((char *) hdrp + SIZEOF_AR_HDR_BIG, namlen, abfd) != namlen) 145284865Sobrien { 145384865Sobrien free (ret); 145484865Sobrien return NULL; 145584865Sobrien } 145684865Sobrien ((char *) hdrp)[SIZEOF_AR_HDR_BIG + namlen] = '\0'; 145784865Sobrien 145884865Sobrien ret->arch_header = (char *) hdrp; 145984865Sobrien /* XXX This actually has to be a call to strtoll (at least on 32-bit 146084865Sobrien machines) since the field width is 20 and there numbers with more 146184865Sobrien than 32 bits can be represented. */ 146284865Sobrien ret->parsed_size = strtol (hdr.size, (char **) NULL, 10); 146384865Sobrien ret->filename = (char *) hdrp + SIZEOF_AR_HDR_BIG; 146484865Sobrien } 146584865Sobrien 146684865Sobrien /* Skip over the XCOFFARFMAG at the end of the file name. */ 146789857Sobrien if (bfd_seek (abfd, (file_ptr) ((namlen & 1) + SXCOFFARFMAG), SEEK_CUR) != 0) 146884865Sobrien return NULL; 146984865Sobrien 147084865Sobrien return (PTR) ret; 147184865Sobrien} 147284865Sobrien 147384865Sobrien/* Open the next element in an XCOFF archive. */ 147484865Sobrien 147584865Sobrienbfd * 147684865Sobrien_bfd_xcoff_openr_next_archived_file (archive, last_file) 147784865Sobrien bfd *archive; 147884865Sobrien bfd *last_file; 147984865Sobrien{ 148084865Sobrien file_ptr filestart; 148184865Sobrien 148284865Sobrien if (xcoff_ardata (archive) == NULL) 148384865Sobrien { 148484865Sobrien bfd_set_error (bfd_error_invalid_operation); 148584865Sobrien return NULL; 148684865Sobrien } 148784865Sobrien 148884865Sobrien if (! xcoff_big_format_p (archive)) 148984865Sobrien { 149084865Sobrien if (last_file == NULL) 149184865Sobrien filestart = bfd_ardata (archive)->first_file_filepos; 149284865Sobrien else 149384865Sobrien filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL, 149484865Sobrien 10); 149584865Sobrien 149684865Sobrien if (filestart == 0 149784865Sobrien || filestart == strtol (xcoff_ardata (archive)->memoff, 149884865Sobrien (char **) NULL, 10) 149984865Sobrien || filestart == strtol (xcoff_ardata (archive)->symoff, 150084865Sobrien (char **) NULL, 10)) 150184865Sobrien { 150284865Sobrien bfd_set_error (bfd_error_no_more_archived_files); 150384865Sobrien return NULL; 150484865Sobrien } 150584865Sobrien } 150684865Sobrien else 150784865Sobrien { 150884865Sobrien if (last_file == NULL) 150984865Sobrien filestart = bfd_ardata (archive)->first_file_filepos; 151084865Sobrien else 151184865Sobrien /* XXX These actually have to be a calls to strtoll (at least 151284865Sobrien on 32-bit machines) since the fields's width is 20 and 151384865Sobrien there numbers with more than 32 bits can be represented. */ 151484865Sobrien filestart = strtol (arch_xhdr_big (last_file)->nextoff, (char **) NULL, 151584865Sobrien 10); 151684865Sobrien 151784865Sobrien /* XXX These actually have to be calls to strtoll (at least on 32-bit 151884865Sobrien machines) since the fields's width is 20 and there numbers with more 151984865Sobrien than 32 bits can be represented. */ 152084865Sobrien if (filestart == 0 152184865Sobrien || filestart == strtol (xcoff_ardata_big (archive)->memoff, 152284865Sobrien (char **) NULL, 10) 152384865Sobrien || filestart == strtol (xcoff_ardata_big (archive)->symoff, 152484865Sobrien (char **) NULL, 10)) 152584865Sobrien { 152684865Sobrien bfd_set_error (bfd_error_no_more_archived_files); 152784865Sobrien return NULL; 152884865Sobrien } 152984865Sobrien } 153084865Sobrien 153184865Sobrien return _bfd_get_elt_at_filepos (archive, filestart); 153284865Sobrien} 153384865Sobrien 153484865Sobrien/* Stat an element in an XCOFF archive. */ 153584865Sobrien 153684865Sobrienint 153792828Sobrien_bfd_xcoff_stat_arch_elt (abfd, s) 153884865Sobrien bfd *abfd; 153984865Sobrien struct stat *s; 154084865Sobrien{ 154184865Sobrien if (abfd->arelt_data == NULL) 154284865Sobrien { 154384865Sobrien bfd_set_error (bfd_error_invalid_operation); 154484865Sobrien return -1; 154584865Sobrien } 154684865Sobrien 154792828Sobrien if (! xcoff_big_format_p (abfd->my_archive)) 154884865Sobrien { 154984865Sobrien struct xcoff_ar_hdr *hdrp = arch_xhdr (abfd); 155084865Sobrien 155184865Sobrien s->st_mtime = strtol (hdrp->date, (char **) NULL, 10); 155284865Sobrien s->st_uid = strtol (hdrp->uid, (char **) NULL, 10); 155384865Sobrien s->st_gid = strtol (hdrp->gid, (char **) NULL, 10); 155484865Sobrien s->st_mode = strtol (hdrp->mode, (char **) NULL, 8); 155584865Sobrien s->st_size = arch_eltdata (abfd)->parsed_size; 155684865Sobrien } 155784865Sobrien else 155884865Sobrien { 155984865Sobrien struct xcoff_ar_hdr_big *hdrp = arch_xhdr_big (abfd); 156084865Sobrien 156184865Sobrien s->st_mtime = strtol (hdrp->date, (char **) NULL, 10); 156284865Sobrien s->st_uid = strtol (hdrp->uid, (char **) NULL, 10); 156384865Sobrien s->st_gid = strtol (hdrp->gid, (char **) NULL, 10); 156484865Sobrien s->st_mode = strtol (hdrp->mode, (char **) NULL, 8); 156584865Sobrien s->st_size = arch_eltdata (abfd)->parsed_size; 156684865Sobrien } 156784865Sobrien 156884865Sobrien return 0; 156984865Sobrien} 157084865Sobrien 157184865Sobrien/* Normalize a file name for inclusion in an archive. */ 157284865Sobrien 157384865Sobrienstatic const char * 157484865Sobriennormalize_filename (abfd) 157584865Sobrien bfd *abfd; 157684865Sobrien{ 157784865Sobrien const char *file; 157884865Sobrien const char *filename; 157984865Sobrien 158084865Sobrien file = bfd_get_filename (abfd); 158184865Sobrien filename = strrchr (file, '/'); 158284865Sobrien if (filename != NULL) 158384865Sobrien filename++; 158484865Sobrien else 158584865Sobrien filename = file; 158684865Sobrien return filename; 158784865Sobrien} 158884865Sobrien 158984865Sobrien/* Write out an XCOFF armap. */ 159084865Sobrien 1591130561Sobrienstatic bfd_boolean 159284865Sobrienxcoff_write_armap_old (abfd, elength, map, orl_count, stridx) 159384865Sobrien bfd *abfd; 159484865Sobrien unsigned int elength ATTRIBUTE_UNUSED; 159584865Sobrien struct orl *map; 159684865Sobrien unsigned int orl_count; 159784865Sobrien int stridx; 159884865Sobrien{ 159984865Sobrien struct xcoff_ar_hdr hdr; 160084865Sobrien char *p; 160184865Sobrien unsigned char buf[4]; 160284865Sobrien bfd *sub; 160384865Sobrien file_ptr fileoff; 160484865Sobrien unsigned int i; 160584865Sobrien 160684865Sobrien memset (&hdr, 0, sizeof hdr); 160784865Sobrien sprintf (hdr.size, "%ld", (long) (4 + orl_count * 4 + stridx)); 160884865Sobrien sprintf (hdr.nextoff, "%d", 0); 160989857Sobrien memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, XCOFFARMAG_ELEMENT_SIZE); 161084865Sobrien sprintf (hdr.date, "%d", 0); 161184865Sobrien sprintf (hdr.uid, "%d", 0); 161284865Sobrien sprintf (hdr.gid, "%d", 0); 161384865Sobrien sprintf (hdr.mode, "%d", 0); 161484865Sobrien sprintf (hdr.namlen, "%d", 0); 161584865Sobrien 161684865Sobrien /* We need spaces, not null bytes, in the header. */ 161784865Sobrien for (p = (char *) &hdr; p < (char *) &hdr + SIZEOF_AR_HDR; p++) 161884865Sobrien if (*p == '\0') 161984865Sobrien *p = ' '; 162084865Sobrien 162189857Sobrien if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR, abfd) 162289857Sobrien != SIZEOF_AR_HDR 162389857Sobrien || (bfd_bwrite (XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd) 162489857Sobrien != SXCOFFARFMAG)) 1625130561Sobrien return FALSE; 162684865Sobrien 162789857Sobrien H_PUT_32 (abfd, orl_count, buf); 162889857Sobrien if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4) 1629130561Sobrien return FALSE; 163084865Sobrien 163184865Sobrien sub = abfd->archive_head; 163284865Sobrien fileoff = SIZEOF_AR_FILE_HDR; 163384865Sobrien i = 0; 163484865Sobrien while (sub != NULL && i < orl_count) 163584865Sobrien { 163684865Sobrien size_t namlen; 163784865Sobrien 163889857Sobrien while (map[i].u.abfd == sub) 163984865Sobrien { 164089857Sobrien H_PUT_32 (abfd, fileoff, buf); 164189857Sobrien if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4) 1642130561Sobrien return FALSE; 164384865Sobrien ++i; 164484865Sobrien } 164584865Sobrien namlen = strlen (normalize_filename (sub)); 164689857Sobrien namlen = (namlen + 1) &~ (size_t) 1; 164784865Sobrien fileoff += (SIZEOF_AR_HDR 164884865Sobrien + namlen 164984865Sobrien + SXCOFFARFMAG 165084865Sobrien + arelt_size (sub)); 165184865Sobrien fileoff = (fileoff + 1) &~ 1; 1652218822Sdim sub = sub->archive_next; 165384865Sobrien } 165484865Sobrien 165584865Sobrien for (i = 0; i < orl_count; i++) 165684865Sobrien { 165784865Sobrien const char *name; 165884865Sobrien size_t namlen; 165984865Sobrien 166084865Sobrien name = *map[i].name; 166184865Sobrien namlen = strlen (name); 166289857Sobrien if (bfd_bwrite (name, (bfd_size_type) (namlen + 1), abfd) != namlen + 1) 1663130561Sobrien return FALSE; 166484865Sobrien } 166584865Sobrien 166684865Sobrien if ((stridx & 1) != 0) 166784865Sobrien { 166884865Sobrien char b; 166984865Sobrien 167084865Sobrien b = '\0'; 167189857Sobrien if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1) 1672130561Sobrien return FALSE; 167384865Sobrien } 167484865Sobrien 1675130561Sobrien return TRUE; 167684865Sobrien} 167784865Sobrien 167889857Sobrienstatic char buff20[XCOFFARMAGBIG_ELEMENT_SIZE + 1]; 167989857Sobrien#define FMT20 "%-20lld" 168089857Sobrien#define FMT12 "%-12d" 168189857Sobrien#define FMT12_OCTAL "%-12o" 168289857Sobrien#define FMT4 "%-4d" 168389857Sobrien#define PRINT20(d, v) \ 168489857Sobrien sprintf (buff20, FMT20, (long long)(v)), \ 168589857Sobrien memcpy ((void *) (d), buff20, 20) 168689857Sobrien 168789857Sobrien#define PRINT12(d, v) \ 168889857Sobrien sprintf (buff20, FMT12, (int)(v)), \ 1689130561Sobrien memcpy ((void *) (d), buff20, 12) 169089857Sobrien 169189857Sobrien#define PRINT12_OCTAL(d, v) \ 169289857Sobrien sprintf (buff20, FMT12_OCTAL, (unsigned int)(v)), \ 169389857Sobrien memcpy ((void *) (d), buff20, 12) 169489857Sobrien 169589857Sobrien#define PRINT4(d, v) \ 169689857Sobrien sprintf (buff20, FMT4, (int)(v)), \ 1697130561Sobrien memcpy ((void *) (d), buff20, 4) 169889857Sobrien 169989857Sobrien#define READ20(d, v) \ 170089857Sobrien buff20[20] = 0, \ 170189857Sobrien memcpy (buff20, (d), 20), \ 170289857Sobrien (v) = bfd_scan_vma (buff20, (const char **) NULL, 10) 170389857Sobrien 1704130561Sobrienstatic bfd_boolean 1705104834Sobriendo_pad (abfd, number) 1706104834Sobrien bfd *abfd; 1707104834Sobrien unsigned int number; 1708104834Sobrien{ 1709104834Sobrien bfd_byte b = 0; 1710104834Sobrien 1711104834Sobrien /* Limit pad to <= 4096. */ 1712104834Sobrien if (number > 4096) 1713130561Sobrien return FALSE; 1714104834Sobrien 1715104834Sobrien while (number--) 1716104834Sobrien if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1) 1717130561Sobrien return FALSE; 1718104834Sobrien 1719130561Sobrien return TRUE; 1720104834Sobrien} 1721104834Sobrien 1722130561Sobrienstatic bfd_boolean 1723104834Sobriendo_copy (out_bfd, in_bfd) 1724104834Sobrien bfd *out_bfd; 1725104834Sobrien bfd *in_bfd; 1726104834Sobrien{ 1727104834Sobrien bfd_size_type remaining; 1728104834Sobrien bfd_byte buffer[DEFAULT_BUFFERSIZE]; 1729104834Sobrien 1730104834Sobrien if (bfd_seek (in_bfd, (file_ptr) 0, SEEK_SET) != 0) 1731130561Sobrien return FALSE; 1732104834Sobrien 1733104834Sobrien remaining = arelt_size (in_bfd); 1734104834Sobrien 1735104834Sobrien while (remaining >= DEFAULT_BUFFERSIZE) 1736104834Sobrien { 1737104834Sobrien if (bfd_bread (buffer, DEFAULT_BUFFERSIZE, in_bfd) != DEFAULT_BUFFERSIZE 1738104834Sobrien || bfd_bwrite (buffer, DEFAULT_BUFFERSIZE, out_bfd) != DEFAULT_BUFFERSIZE) 1739130561Sobrien return FALSE; 1740104834Sobrien 1741104834Sobrien remaining -= DEFAULT_BUFFERSIZE; 1742104834Sobrien } 1743104834Sobrien 1744104834Sobrien if (remaining) 1745104834Sobrien { 1746130561Sobrien if (bfd_bread (buffer, remaining, in_bfd) != remaining 1747104834Sobrien || bfd_bwrite (buffer, remaining, out_bfd) != remaining) 1748130561Sobrien return FALSE; 1749104834Sobrien } 1750104834Sobrien 1751130561Sobrien return TRUE; 1752104834Sobrien} 1753104834Sobrien 1754130561Sobrienstatic bfd_boolean 1755104834Sobriendo_shared_object_padding (out_bfd, in_bfd, offset, ar_header_size) 1756104834Sobrien bfd *out_bfd; 1757104834Sobrien bfd *in_bfd; 1758218822Sdim file_ptr *offset; 1759104834Sobrien int ar_header_size; 1760104834Sobrien{ 1761104834Sobrien if (bfd_check_format (in_bfd, bfd_object) 1762104834Sobrien && bfd_get_flavour (in_bfd) == bfd_target_xcoff_flavour 1763104834Sobrien && (in_bfd->flags & DYNAMIC) != 0) 1764104834Sobrien { 1765104834Sobrien bfd_size_type pad = 0; 1766104834Sobrien int text_align_power; 1767104834Sobrien 1768104834Sobrien text_align_power = bfd_xcoff_text_align_power (in_bfd); 1769104834Sobrien 1770104834Sobrien pad = 1 << text_align_power; 1771104834Sobrien pad -= (*offset + ar_header_size) & (pad - 1); 1772104834Sobrien 1773104834Sobrien if (! do_pad (out_bfd, pad)) 1774130561Sobrien return FALSE; 1775104834Sobrien 1776104834Sobrien *offset += pad; 1777104834Sobrien } 1778104834Sobrien 1779130561Sobrien return TRUE; 1780104834Sobrien} 1781104834Sobrien 1782130561Sobrienstatic bfd_boolean 178389857Sobrienxcoff_write_armap_big (abfd, elength, map, orl_count, stridx) 178484865Sobrien bfd *abfd; 178589857Sobrien unsigned int elength ATTRIBUTE_UNUSED; 178684865Sobrien struct orl *map; 178784865Sobrien unsigned int orl_count; 178889857Sobrien int stridx; 178984865Sobrien{ 179089857Sobrien struct xcoff_ar_file_hdr_big *fhdr; 179189857Sobrien bfd_vma i, sym_32, sym_64, str_32, str_64; 179284865Sobrien const bfd_arch_info_type *arch_info = NULL; 179389857Sobrien bfd *current_bfd; 179489857Sobrien size_t string_length; 1795218822Sdim file_ptr nextoff, prevoff; 1796130561Sobrien 179789857Sobrien /* First, we look through the symbols and work out which are 179889857Sobrien from 32-bit objects and which from 64-bit ones. */ 179989857Sobrien sym_32 = sym_64 = str_32 = str_64 = 0; 180084865Sobrien 180189857Sobrien current_bfd = abfd->archive_head; 180289857Sobrien if (current_bfd != NULL) 180389857Sobrien arch_info = bfd_get_arch_info (current_bfd); 180489857Sobrien i = 0; 180589857Sobrien while (current_bfd != NULL && i < orl_count) 180689857Sobrien { 180789857Sobrien while (map[i].u.abfd == current_bfd) 180889857Sobrien { 180989857Sobrien string_length = strlen (*map[i].name) + 1; 181084865Sobrien 181189857Sobrien if (arch_info->bits_per_address == 64) 181289857Sobrien { 181389857Sobrien sym_64++; 181489857Sobrien str_64 += string_length; 181589857Sobrien } 181689857Sobrien else 181789857Sobrien { 181889857Sobrien sym_32++; 181989857Sobrien str_32 += string_length; 182089857Sobrien } 182189857Sobrien i++; 182289857Sobrien } 1823218822Sdim current_bfd = current_bfd->archive_next; 182489857Sobrien if (current_bfd != NULL) 182589857Sobrien arch_info = bfd_get_arch_info (current_bfd); 182689857Sobrien } 182784865Sobrien 182889857Sobrien /* A quick sanity check... */ 182989857Sobrien BFD_ASSERT (sym_64 + sym_32 == orl_count); 183089857Sobrien /* Explicit cast to int for compiler. */ 183189857Sobrien BFD_ASSERT ((int)(str_64 + str_32) == stridx); 183284865Sobrien 183389857Sobrien fhdr = xcoff_ardata_big (abfd); 183484865Sobrien 183589857Sobrien /* xcoff_write_archive_contents_big passes nextoff in symoff. */ 183689857Sobrien READ20 (fhdr->memoff, prevoff); 183789857Sobrien READ20 (fhdr->symoff, nextoff); 183884865Sobrien 183989857Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 184089857Sobrien 1841130561Sobrien /* Write out the symbol table. 1842130561Sobrien Layout : 1843130561Sobrien 184489857Sobrien standard big archive header 1845130561Sobrien 0x0000 ar_size [0x14] 1846130561Sobrien 0x0014 ar_nxtmem [0x14] 1847130561Sobrien 0x0028 ar_prvmem [0x14] 1848130561Sobrien 0x003C ar_date [0x0C] 1849130561Sobrien 0x0048 ar_uid [0x0C] 1850130561Sobrien 0x0054 ar_gid [0x0C] 1851130561Sobrien 0x0060 ar_mod [0x0C] 1852130561Sobrien 0x006C ar_namelen[0x04] 1853130561Sobrien 0x0070 ar_fmag [SXCOFFARFMAG] 1854130561Sobrien 1855130561Sobrien Symbol table 1856130561Sobrien 0x0072 num_syms [0x08], binary 1857130561Sobrien 0x0078 offsets [0x08 * num_syms], binary 1858130561Sobrien 0x0086 + 0x08 * num_syms names [??] 1859130561Sobrien ?? pad to even bytes. 186089857Sobrien */ 186189857Sobrien 1862130561Sobrien if (sym_32) 186384865Sobrien { 186489857Sobrien struct xcoff_ar_hdr_big *hdr; 1865218822Sdim char *symbol_table; 1866218822Sdim char *st; 186789857Sobrien file_ptr fileoff; 186884865Sobrien 1869130561Sobrien bfd_vma symbol_table_size = 187089857Sobrien SIZEOF_AR_HDR_BIG 187189857Sobrien + SXCOFFARFMAG 1872130561Sobrien + 8 1873130561Sobrien + 8 * sym_32 187489857Sobrien + str_32 + (str_32 & 1); 187589857Sobrien 1876218822Sdim symbol_table = bfd_zmalloc (symbol_table_size); 187789857Sobrien if (symbol_table == NULL) 1878130561Sobrien return FALSE; 187989857Sobrien 188089857Sobrien hdr = (struct xcoff_ar_hdr_big *) symbol_table; 1881130561Sobrien 188289857Sobrien PRINT20 (hdr->size, 8 + 8 * sym_32 + str_32 + (str_32 & 1)); 1883130561Sobrien 188489857Sobrien if (sym_64) 188589857Sobrien PRINT20 (hdr->nextoff, nextoff + symbol_table_size); 188684865Sobrien else 188789857Sobrien PRINT20 (hdr->nextoff, 0); 188884865Sobrien 188989857Sobrien PRINT20 (hdr->prevoff, prevoff); 189089857Sobrien PRINT12 (hdr->date, 0); 189189857Sobrien PRINT12 (hdr->uid, 0); 189289857Sobrien PRINT12 (hdr->gid, 0); 189389857Sobrien PRINT12 (hdr->mode, 0); 189489857Sobrien PRINT4 (hdr->namlen, 0) ; 189584865Sobrien 189689857Sobrien st = symbol_table + SIZEOF_AR_HDR_BIG; 189789857Sobrien memcpy (st, XCOFFARFMAG, SXCOFFARFMAG); 189889857Sobrien st += SXCOFFARFMAG; 189984865Sobrien 190089857Sobrien bfd_h_put_64 (abfd, sym_32, st); 190189857Sobrien st += 8; 1902130561Sobrien 190389857Sobrien /* loop over the 32 bit offsets */ 190489857Sobrien current_bfd = abfd->archive_head; 190589857Sobrien if (current_bfd != NULL) 190689857Sobrien arch_info = bfd_get_arch_info (current_bfd); 190789857Sobrien fileoff = SIZEOF_AR_FILE_HDR_BIG; 190889857Sobrien i = 0; 190989857Sobrien while (current_bfd != NULL && i < orl_count) 191089857Sobrien { 191189857Sobrien while (map[i].u.abfd == current_bfd) 191289857Sobrien { 191389857Sobrien if (arch_info->bits_per_address == 32) 191489857Sobrien { 191589857Sobrien bfd_h_put_64 (abfd, fileoff, st); 191689857Sobrien st += 8; 191789857Sobrien } 191889857Sobrien i++; 191989857Sobrien } 192089857Sobrien string_length = strlen (normalize_filename (current_bfd)); 192189857Sobrien string_length += string_length & 1; 192289857Sobrien fileoff += (SIZEOF_AR_HDR_BIG 192389857Sobrien + string_length 192489857Sobrien + SXCOFFARFMAG 192589857Sobrien + arelt_size (current_bfd)); 192689857Sobrien fileoff += fileoff & 1; 1927218822Sdim current_bfd = current_bfd->archive_next; 192889857Sobrien if (current_bfd != NULL) 192989857Sobrien arch_info = bfd_get_arch_info (current_bfd); 193089857Sobrien } 193184865Sobrien 193289857Sobrien /* loop over the 32 bit symbol names */ 193389857Sobrien current_bfd = abfd->archive_head; 193489857Sobrien if (current_bfd != NULL) 193589857Sobrien arch_info = bfd_get_arch_info (current_bfd); 193689857Sobrien i = 0; 193789857Sobrien while (current_bfd != NULL && i < orl_count) 193889857Sobrien { 193989857Sobrien while (map[i].u.abfd == current_bfd) 194089857Sobrien { 194189857Sobrien if (arch_info->bits_per_address == 32) 194289857Sobrien { 194389857Sobrien string_length = sprintf (st, "%s", *map[i].name); 194489857Sobrien st += string_length + 1; 194589857Sobrien } 194689857Sobrien i++; 194789857Sobrien } 1948218822Sdim current_bfd = current_bfd->archive_next; 194989857Sobrien if (current_bfd != NULL) 195089857Sobrien arch_info = bfd_get_arch_info (current_bfd); 195189857Sobrien } 195284865Sobrien 195389857Sobrien bfd_bwrite (symbol_table, symbol_table_size, abfd); 195489857Sobrien 195589857Sobrien free (symbol_table); 195689857Sobrien 195789857Sobrien prevoff = nextoff; 195889857Sobrien nextoff = nextoff + symbol_table_size; 195984865Sobrien } 1960130561Sobrien else 196189857Sobrien PRINT20 (fhdr->symoff, 0); 1962130561Sobrien 1963130561Sobrien if (sym_64) 196484865Sobrien { 196589857Sobrien struct xcoff_ar_hdr_big *hdr; 1966218822Sdim char *symbol_table; 1967218822Sdim char *st; 196889857Sobrien file_ptr fileoff; 196984865Sobrien 1970130561Sobrien bfd_vma symbol_table_size = 197189857Sobrien SIZEOF_AR_HDR_BIG 197289857Sobrien + SXCOFFARFMAG 1973130561Sobrien + 8 1974130561Sobrien + 8 * sym_64 197589857Sobrien + str_64 + (str_64 & 1); 197689857Sobrien 1977218822Sdim symbol_table = bfd_zmalloc (symbol_table_size); 197889857Sobrien if (symbol_table == NULL) 1979130561Sobrien return FALSE; 198084865Sobrien 198189857Sobrien hdr = (struct xcoff_ar_hdr_big *) symbol_table; 198284865Sobrien 198389857Sobrien PRINT20 (hdr->size, 8 + 8 * sym_64 + str_64 + (str_64 & 1)); 198489857Sobrien PRINT20 (hdr->nextoff, 0); 198589857Sobrien PRINT20 (hdr->prevoff, prevoff); 198689857Sobrien PRINT12 (hdr->date, 0); 198789857Sobrien PRINT12 (hdr->uid, 0); 198889857Sobrien PRINT12 (hdr->gid, 0); 198989857Sobrien PRINT12 (hdr->mode, 0); 199089857Sobrien PRINT4 (hdr->namlen, 0); 199184865Sobrien 199289857Sobrien st = symbol_table + SIZEOF_AR_HDR_BIG; 199389857Sobrien memcpy (st, XCOFFARFMAG, SXCOFFARFMAG); 199489857Sobrien st += SXCOFFARFMAG; 199589857Sobrien 199689857Sobrien bfd_h_put_64 (abfd, sym_64, st); 199789857Sobrien st += 8; 1998130561Sobrien 199989857Sobrien /* loop over the 64 bit offsets */ 200089857Sobrien current_bfd = abfd->archive_head; 200189857Sobrien if (current_bfd != NULL) 200289857Sobrien arch_info = bfd_get_arch_info (current_bfd); 200389857Sobrien fileoff = SIZEOF_AR_FILE_HDR_BIG; 200489857Sobrien i = 0; 200589857Sobrien while (current_bfd != NULL && i < orl_count) 200684865Sobrien { 200789857Sobrien while (map[i].u.abfd == current_bfd) 200889857Sobrien { 200989857Sobrien if (arch_info->bits_per_address == 64) 201089857Sobrien { 201189857Sobrien bfd_h_put_64 (abfd, fileoff, st); 201289857Sobrien st += 8; 201389857Sobrien } 201489857Sobrien i++; 201589857Sobrien } 201689857Sobrien string_length = strlen (normalize_filename (current_bfd)); 201789857Sobrien string_length += string_length & 1; 201889857Sobrien fileoff += (SIZEOF_AR_HDR_BIG 201989857Sobrien + string_length 202089857Sobrien + SXCOFFARFMAG 202189857Sobrien + arelt_size (current_bfd)); 202289857Sobrien fileoff += fileoff & 1; 2023218822Sdim current_bfd = current_bfd->archive_next; 202489857Sobrien if (current_bfd != NULL) 202589857Sobrien arch_info = bfd_get_arch_info (current_bfd); 202684865Sobrien } 202789857Sobrien 202889857Sobrien /* loop over the 64 bit symbol names */ 202989857Sobrien current_bfd = abfd->archive_head; 203089857Sobrien if (current_bfd != NULL) 203189857Sobrien arch_info = bfd_get_arch_info (current_bfd); 203289857Sobrien i = 0; 203389857Sobrien while (current_bfd != NULL && i < orl_count) 203484865Sobrien { 203589857Sobrien while (map[i].u.abfd == current_bfd) 203689857Sobrien { 203789857Sobrien if (arch_info->bits_per_address == 64) 203889857Sobrien { 203989857Sobrien string_length = sprintf (st, "%s", *map[i].name); 204089857Sobrien st += string_length + 1; 204189857Sobrien } 204289857Sobrien i++; 204389857Sobrien } 2044218822Sdim current_bfd = current_bfd->archive_next; 204589857Sobrien if (current_bfd != NULL) 204689857Sobrien arch_info = bfd_get_arch_info (current_bfd); 204784865Sobrien } 204884865Sobrien 204989857Sobrien bfd_bwrite (symbol_table, symbol_table_size, abfd); 205084865Sobrien 205189857Sobrien free (symbol_table); 205289857Sobrien 205389857Sobrien PRINT20 (fhdr->symoff64, nextoff); 205489857Sobrien } 2055130561Sobrien else 205689857Sobrien PRINT20 (fhdr->symoff64, 0); 2057130561Sobrien 2058130561Sobrien return TRUE; 205984865Sobrien} 206084865Sobrien 2061130561Sobrienbfd_boolean 206284865Sobrien_bfd_xcoff_write_armap (abfd, elength, map, orl_count, stridx) 206384865Sobrien bfd *abfd; 206484865Sobrien unsigned int elength ATTRIBUTE_UNUSED; 206584865Sobrien struct orl *map; 206684865Sobrien unsigned int orl_count; 206784865Sobrien int stridx; 206884865Sobrien{ 206984865Sobrien if (! xcoff_big_format_p (abfd)) 207084865Sobrien return xcoff_write_armap_old (abfd, elength, map, orl_count, stridx); 207184865Sobrien else 207284865Sobrien return xcoff_write_armap_big (abfd, elength, map, orl_count, stridx); 207384865Sobrien} 207484865Sobrien 207584865Sobrien/* Write out an XCOFF archive. We always write an entire archive, 207684865Sobrien rather than fussing with the freelist and so forth. */ 207784865Sobrien 2078130561Sobrienstatic bfd_boolean 207984865Sobrienxcoff_write_archive_contents_old (abfd) 208084865Sobrien bfd *abfd; 208184865Sobrien{ 208284865Sobrien struct xcoff_ar_file_hdr fhdr; 208389857Sobrien bfd_size_type count; 208489857Sobrien bfd_size_type total_namlen; 208584865Sobrien file_ptr *offsets; 2086130561Sobrien bfd_boolean makemap; 2087130561Sobrien bfd_boolean hasobjects; 2088218822Sdim file_ptr prevoff, nextoff; 208984865Sobrien bfd *sub; 209089857Sobrien size_t i; 209184865Sobrien struct xcoff_ar_hdr ahdr; 209284865Sobrien bfd_size_type size; 209384865Sobrien char *p; 209489857Sobrien char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1]; 209584865Sobrien 209684865Sobrien memset (&fhdr, 0, sizeof fhdr); 2097218822Sdim (void) strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG); 209884865Sobrien sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR); 209984865Sobrien sprintf (fhdr.freeoff, "%d", 0); 210084865Sobrien 210184865Sobrien count = 0; 210284865Sobrien total_namlen = 0; 2103218822Sdim for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_next) 210484865Sobrien { 210584865Sobrien ++count; 210684865Sobrien total_namlen += strlen (normalize_filename (sub)) + 1; 210784865Sobrien } 210884865Sobrien offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr)); 210984865Sobrien if (offsets == NULL) 2110130561Sobrien return FALSE; 211184865Sobrien 211289857Sobrien if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0) 2113130561Sobrien return FALSE; 211484865Sobrien 211584865Sobrien makemap = bfd_has_map (abfd); 2116130561Sobrien hasobjects = FALSE; 211784865Sobrien prevoff = 0; 211884865Sobrien nextoff = SIZEOF_AR_FILE_HDR; 2119218822Sdim for (sub = abfd->archive_head, i = 0; 2120218822Sdim sub != NULL; 2121218822Sdim sub = sub->archive_next, i++) 212284865Sobrien { 212384865Sobrien const char *name; 212489857Sobrien bfd_size_type namlen; 212584865Sobrien struct xcoff_ar_hdr *ahdrp; 212684865Sobrien bfd_size_type remaining; 212784865Sobrien 212884865Sobrien if (makemap && ! hasobjects) 212984865Sobrien { 213084865Sobrien if (bfd_check_format (sub, bfd_object)) 2131130561Sobrien hasobjects = TRUE; 213284865Sobrien } 213384865Sobrien 213484865Sobrien name = normalize_filename (sub); 213584865Sobrien namlen = strlen (name); 213684865Sobrien 213784865Sobrien if (sub->arelt_data != NULL) 213884865Sobrien ahdrp = arch_xhdr (sub); 213984865Sobrien else 214084865Sobrien ahdrp = NULL; 214184865Sobrien 214284865Sobrien if (ahdrp == NULL) 214384865Sobrien { 214484865Sobrien struct stat s; 214584865Sobrien 214684865Sobrien memset (&ahdr, 0, sizeof ahdr); 214784865Sobrien ahdrp = &ahdr; 214884865Sobrien if (stat (bfd_get_filename (sub), &s) != 0) 214984865Sobrien { 215084865Sobrien bfd_set_error (bfd_error_system_call); 2151130561Sobrien return FALSE; 215284865Sobrien } 215384865Sobrien 215484865Sobrien sprintf (ahdrp->size, "%ld", (long) s.st_size); 215584865Sobrien sprintf (ahdrp->date, "%ld", (long) s.st_mtime); 215684865Sobrien sprintf (ahdrp->uid, "%ld", (long) s.st_uid); 215784865Sobrien sprintf (ahdrp->gid, "%ld", (long) s.st_gid); 215884865Sobrien sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode); 215984865Sobrien 216084865Sobrien if (sub->arelt_data == NULL) 216184865Sobrien { 216289857Sobrien size = sizeof (struct areltdata); 216389857Sobrien sub->arelt_data = bfd_alloc (sub, size); 216484865Sobrien if (sub->arelt_data == NULL) 2165130561Sobrien return FALSE; 216684865Sobrien } 216784865Sobrien 216884865Sobrien arch_eltdata (sub)->parsed_size = s.st_size; 216984865Sobrien } 217084865Sobrien 217184865Sobrien sprintf (ahdrp->prevoff, "%ld", (long) prevoff); 217284865Sobrien sprintf (ahdrp->namlen, "%ld", (long) namlen); 217384865Sobrien 217484865Sobrien /* If the length of the name is odd, we write out the null byte 2175130561Sobrien after the name as well. */ 217689857Sobrien namlen = (namlen + 1) &~ (bfd_size_type) 1; 217784865Sobrien 217884865Sobrien remaining = arelt_size (sub); 217984865Sobrien size = (SIZEOF_AR_HDR 218084865Sobrien + namlen 218184865Sobrien + SXCOFFARFMAG 218284865Sobrien + remaining); 218384865Sobrien 218484865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 218584865Sobrien 218684865Sobrien offsets[i] = nextoff; 218784865Sobrien 218884865Sobrien prevoff = nextoff; 218984865Sobrien nextoff += size + (size & 1); 219084865Sobrien 219184865Sobrien sprintf (ahdrp->nextoff, "%ld", (long) nextoff); 219284865Sobrien 219384865Sobrien /* We need spaces, not null bytes, in the header. */ 219484865Sobrien for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++) 219584865Sobrien if (*p == '\0') 219684865Sobrien *p = ' '; 219784865Sobrien 219889857Sobrien if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR, abfd) 219989857Sobrien != SIZEOF_AR_HDR) 2200130561Sobrien || bfd_bwrite ((PTR) name, namlen, abfd) != namlen 2201130561Sobrien || bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, 2202130561Sobrien abfd) != SXCOFFARFMAG) 2203130561Sobrien return FALSE; 220484865Sobrien 220584865Sobrien if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0) 2206130561Sobrien return FALSE; 220784865Sobrien 2208104834Sobrien if (! do_copy (abfd, sub)) 2209130561Sobrien return FALSE; 2210130561Sobrien 2211104834Sobrien if (! do_pad (abfd, size & 1)) 2212130561Sobrien return FALSE; 221384865Sobrien } 221484865Sobrien 221584865Sobrien sprintf (fhdr.lastmemoff, "%ld", (long) prevoff); 221684865Sobrien 221784865Sobrien /* Write out the member table. */ 221884865Sobrien 221984865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 222084865Sobrien sprintf (fhdr.memoff, "%ld", (long) nextoff); 222184865Sobrien 222284865Sobrien memset (&ahdr, 0, sizeof ahdr); 2223104834Sobrien sprintf (ahdr.size, "%ld", (long) (XCOFFARMAG_ELEMENT_SIZE 2224104834Sobrien + count * XCOFFARMAG_ELEMENT_SIZE 2225104834Sobrien + total_namlen)); 222684865Sobrien sprintf (ahdr.prevoff, "%ld", (long) prevoff); 222784865Sobrien sprintf (ahdr.date, "%d", 0); 222884865Sobrien sprintf (ahdr.uid, "%d", 0); 222984865Sobrien sprintf (ahdr.gid, "%d", 0); 223084865Sobrien sprintf (ahdr.mode, "%d", 0); 223184865Sobrien sprintf (ahdr.namlen, "%d", 0); 223284865Sobrien 223384865Sobrien size = (SIZEOF_AR_HDR 223489857Sobrien + XCOFFARMAG_ELEMENT_SIZE 223589857Sobrien + count * XCOFFARMAG_ELEMENT_SIZE 223684865Sobrien + total_namlen 223784865Sobrien + SXCOFFARFMAG); 223884865Sobrien 223984865Sobrien prevoff = nextoff; 224084865Sobrien nextoff += size + (size & 1); 224184865Sobrien 224284865Sobrien if (makemap && hasobjects) 224384865Sobrien sprintf (ahdr.nextoff, "%ld", (long) nextoff); 224484865Sobrien else 224584865Sobrien sprintf (ahdr.nextoff, "%d", 0); 224684865Sobrien 224784865Sobrien /* We need spaces, not null bytes, in the header. */ 224884865Sobrien for (p = (char *) &ahdr; p < (char *) &ahdr + SIZEOF_AR_HDR; p++) 224984865Sobrien if (*p == '\0') 225084865Sobrien *p = ' '; 225184865Sobrien 225289857Sobrien if ((bfd_bwrite ((PTR) &ahdr, (bfd_size_type) SIZEOF_AR_HDR, abfd) 225389857Sobrien != SIZEOF_AR_HDR) 225489857Sobrien || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd) 225584865Sobrien != SXCOFFARFMAG)) 2256130561Sobrien return FALSE; 225784865Sobrien 225884865Sobrien sprintf (decbuf, "%-12ld", (long) count); 225989857Sobrien if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE, abfd) 226089857Sobrien != XCOFFARMAG_ELEMENT_SIZE) 2261130561Sobrien return FALSE; 226289857Sobrien for (i = 0; i < (size_t) count; i++) 226384865Sobrien { 226484865Sobrien sprintf (decbuf, "%-12ld", (long) offsets[i]); 2265130561Sobrien if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE, 226689857Sobrien abfd) != XCOFFARMAG_ELEMENT_SIZE) 2267130561Sobrien return FALSE; 226884865Sobrien } 2269218822Sdim for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_next) 227084865Sobrien { 227184865Sobrien const char *name; 227289857Sobrien bfd_size_type namlen; 227384865Sobrien 227484865Sobrien name = normalize_filename (sub); 227584865Sobrien namlen = strlen (name); 227689857Sobrien if (bfd_bwrite ((PTR) name, namlen + 1, abfd) != namlen + 1) 2277130561Sobrien return FALSE; 227884865Sobrien } 227984865Sobrien 2280104834Sobrien if (! do_pad (abfd, size & 1)) 2281130561Sobrien return FALSE; 228284865Sobrien 228384865Sobrien /* Write out the armap, if appropriate. */ 228484865Sobrien if (! makemap || ! hasobjects) 228584865Sobrien sprintf (fhdr.symoff, "%d", 0); 228684865Sobrien else 228784865Sobrien { 228884865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 228984865Sobrien sprintf (fhdr.symoff, "%ld", (long) nextoff); 229084865Sobrien bfd_ardata (abfd)->tdata = (PTR) &fhdr; 229184865Sobrien if (! _bfd_compute_and_write_armap (abfd, 0)) 2292130561Sobrien return FALSE; 229384865Sobrien } 229484865Sobrien 229584865Sobrien /* Write out the archive file header. */ 229684865Sobrien 229784865Sobrien /* We need spaces, not null bytes, in the header. */ 229884865Sobrien for (p = (char *) &fhdr; p < (char *) &fhdr + SIZEOF_AR_FILE_HDR; p++) 229984865Sobrien if (*p == '\0') 230084865Sobrien *p = ' '; 230184865Sobrien 230284865Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 230389857Sobrien || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR, abfd) 230489857Sobrien != SIZEOF_AR_FILE_HDR)) 2305130561Sobrien return FALSE; 230684865Sobrien 2307130561Sobrien return TRUE; 230884865Sobrien} 230984865Sobrien 2310130561Sobrienstatic bfd_boolean 231184865Sobrienxcoff_write_archive_contents_big (abfd) 231284865Sobrien bfd *abfd; 231384865Sobrien{ 231484865Sobrien struct xcoff_ar_file_hdr_big fhdr; 231589857Sobrien bfd_size_type count; 231689857Sobrien bfd_size_type total_namlen; 231784865Sobrien file_ptr *offsets; 2318130561Sobrien bfd_boolean makemap; 2319130561Sobrien bfd_boolean hasobjects; 2320218822Sdim file_ptr prevoff, nextoff; 232189857Sobrien bfd *current_bfd; 232289857Sobrien size_t i; 232389857Sobrien struct xcoff_ar_hdr_big *hdr, ahdr; 232484865Sobrien bfd_size_type size; 2325218822Sdim char *member_table, *mt; 232689857Sobrien bfd_vma member_table_size; 232784865Sobrien 2328104834Sobrien memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG); 232989857Sobrien memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG); 233084865Sobrien 2331104834Sobrien if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR_BIG, SEEK_SET) != 0) 2332130561Sobrien return FALSE; 2333130561Sobrien 2334104834Sobrien /* Calculate count and total_namlen. */ 2335104834Sobrien makemap = bfd_has_map (abfd); 2336130561Sobrien hasobjects = FALSE; 2337130561Sobrien for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0; 2338130561Sobrien current_bfd != NULL; 2339218822Sdim current_bfd = current_bfd->archive_next, count++) 2340104834Sobrien { 2341104834Sobrien total_namlen += strlen (normalize_filename (current_bfd)) + 1; 234289857Sobrien 2343104834Sobrien if (makemap 2344104834Sobrien && ! hasobjects 2345104834Sobrien && bfd_check_format (current_bfd, bfd_object)) 2346130561Sobrien hasobjects = TRUE; 2347104834Sobrien } 2348104834Sobrien 234989857Sobrien offsets = NULL; 235089857Sobrien if (count) 235184865Sobrien { 235289857Sobrien offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr)); 235389857Sobrien if (offsets == NULL) 2354130561Sobrien return FALSE; 235584865Sobrien } 235684865Sobrien 235784865Sobrien prevoff = 0; 235884865Sobrien nextoff = SIZEOF_AR_FILE_HDR_BIG; 2359130561Sobrien for (current_bfd = abfd->archive_head, i = 0; 2360130561Sobrien current_bfd != NULL; 2361218822Sdim current_bfd = current_bfd->archive_next, i++) 236284865Sobrien { 236384865Sobrien const char *name; 236489857Sobrien bfd_size_type namlen; 236584865Sobrien struct xcoff_ar_hdr_big *ahdrp; 236684865Sobrien bfd_size_type remaining; 236784865Sobrien 236889857Sobrien name = normalize_filename (current_bfd); 236984865Sobrien namlen = strlen (name); 237084865Sobrien 237189857Sobrien if (current_bfd->arelt_data != NULL) 237289857Sobrien ahdrp = arch_xhdr_big (current_bfd); 237384865Sobrien else 237484865Sobrien ahdrp = NULL; 237584865Sobrien 237684865Sobrien if (ahdrp == NULL) 237784865Sobrien { 237884865Sobrien struct stat s; 237984865Sobrien 238084865Sobrien ahdrp = &ahdr; 238184865Sobrien /* XXX This should actually be a call to stat64 (at least on 2382130561Sobrien 32-bit machines). 238389857Sobrien XXX This call will fail if the original object is not found. */ 238489857Sobrien if (stat (bfd_get_filename (current_bfd), &s) != 0) 238584865Sobrien { 238684865Sobrien bfd_set_error (bfd_error_system_call); 2387130561Sobrien return FALSE; 238884865Sobrien } 238984865Sobrien 239089857Sobrien PRINT20 (ahdrp->size, s.st_size); 239189857Sobrien PRINT12 (ahdrp->date, s.st_mtime); 239289857Sobrien PRINT12 (ahdrp->uid, s.st_uid); 239389857Sobrien PRINT12 (ahdrp->gid, s.st_gid); 239489857Sobrien PRINT12_OCTAL (ahdrp->mode, s.st_mode); 239584865Sobrien 239689857Sobrien if (current_bfd->arelt_data == NULL) 239784865Sobrien { 239889857Sobrien size = sizeof (struct areltdata); 239989857Sobrien current_bfd->arelt_data = bfd_alloc (current_bfd, size); 240089857Sobrien if (current_bfd->arelt_data == NULL) 2401130561Sobrien return FALSE; 240284865Sobrien } 240384865Sobrien 240489857Sobrien arch_eltdata (current_bfd)->parsed_size = s.st_size; 240584865Sobrien } 240684865Sobrien 240789857Sobrien PRINT20 (ahdrp->prevoff, prevoff); 240889857Sobrien PRINT4 (ahdrp->namlen, namlen); 240984865Sobrien 241084865Sobrien /* If the length of the name is odd, we write out the null byte 2411130561Sobrien after the name as well. */ 241289857Sobrien namlen = (namlen + 1) &~ (bfd_size_type) 1; 241384865Sobrien 241489857Sobrien remaining = arelt_size (current_bfd); 241584865Sobrien size = (SIZEOF_AR_HDR_BIG 241684865Sobrien + namlen 241784865Sobrien + SXCOFFARFMAG 241884865Sobrien + remaining); 241984865Sobrien 242084865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 242184865Sobrien 2422104834Sobrien /* Check for xcoff shared objects. 2423104834Sobrien Their text section needs to be aligned wrt the archive file position. 2424104834Sobrien This requires extra padding before the archive header. */ 2425104834Sobrien if (! do_shared_object_padding (abfd, current_bfd, & nextoff, 2426130561Sobrien SIZEOF_AR_HDR_BIG + namlen 2427104834Sobrien + SXCOFFARFMAG)) 2428130561Sobrien return FALSE; 2429104834Sobrien 243084865Sobrien offsets[i] = nextoff; 243184865Sobrien 243284865Sobrien prevoff = nextoff; 243384865Sobrien nextoff += size + (size & 1); 243484865Sobrien 243589857Sobrien PRINT20 (ahdrp->nextoff, nextoff); 243684865Sobrien 243789857Sobrien if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd) 243889857Sobrien != SIZEOF_AR_HDR_BIG) 243989857Sobrien || bfd_bwrite ((PTR) name, (bfd_size_type) namlen, abfd) != namlen 2440130561Sobrien || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, 244189857Sobrien abfd) != SXCOFFARFMAG)) 2442130561Sobrien return FALSE; 244384865Sobrien 244489857Sobrien if (bfd_seek (current_bfd, (file_ptr) 0, SEEK_SET) != 0) 2445130561Sobrien return FALSE; 244684865Sobrien 2447104834Sobrien if (! do_copy (abfd, current_bfd)) 2448130561Sobrien return FALSE; 2449130561Sobrien 2450104834Sobrien if (! do_pad (abfd, size & 1)) 2451130561Sobrien return FALSE; 2452104834Sobrien } 245384865Sobrien 2454104834Sobrien if (count) 2455104834Sobrien { 2456104834Sobrien PRINT20 (fhdr.firstmemoff, offsets[0]); 2457104834Sobrien PRINT20 (fhdr.lastmemoff, prevoff); 245884865Sobrien } 245984865Sobrien 2460130561Sobrien /* Write out the member table. 2461130561Sobrien Layout : 246284865Sobrien 246389857Sobrien standard big archive header 2464130561Sobrien 0x0000 ar_size [0x14] 2465130561Sobrien 0x0014 ar_nxtmem [0x14] 2466130561Sobrien 0x0028 ar_prvmem [0x14] 2467130561Sobrien 0x003C ar_date [0x0C] 2468130561Sobrien 0x0048 ar_uid [0x0C] 2469130561Sobrien 0x0054 ar_gid [0x0C] 2470130561Sobrien 0x0060 ar_mod [0x0C] 2471130561Sobrien 0x006C ar_namelen[0x04] 2472130561Sobrien 0x0070 ar_fmag [0x02] 247389857Sobrien 2474130561Sobrien Member table 2475130561Sobrien 0x0072 count [0x14] 2476130561Sobrien 0x0086 offsets [0x14 * counts] 2477130561Sobrien 0x0086 + 0x14 * counts names [??] 2478130561Sobrien ?? pad to even bytes. 247989857Sobrien */ 248089857Sobrien 248184865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 248284865Sobrien 248389857Sobrien member_table_size = (SIZEOF_AR_HDR_BIG 248489857Sobrien + SXCOFFARFMAG 248589857Sobrien + XCOFFARMAGBIG_ELEMENT_SIZE 248689857Sobrien + count * XCOFFARMAGBIG_ELEMENT_SIZE 248789857Sobrien + total_namlen); 248884865Sobrien 248989857Sobrien member_table_size += member_table_size & 1; 2490218822Sdim member_table = bfd_zmalloc (member_table_size); 249189857Sobrien if (member_table == NULL) 2492130561Sobrien return FALSE; 249384865Sobrien 249489857Sobrien hdr = (struct xcoff_ar_hdr_big *) member_table; 249584865Sobrien 2496104834Sobrien PRINT20 (hdr->size, (XCOFFARMAGBIG_ELEMENT_SIZE 2497104834Sobrien + count * XCOFFARMAGBIG_ELEMENT_SIZE 2498104834Sobrien + total_namlen + (total_namlen & 1))); 2499130561Sobrien if (makemap && hasobjects) 250089857Sobrien PRINT20 (hdr->nextoff, nextoff + member_table_size); 250184865Sobrien else 250289857Sobrien PRINT20 (hdr->nextoff, 0); 250389857Sobrien PRINT20 (hdr->prevoff, prevoff); 250489857Sobrien PRINT12 (hdr->date, 0); 250589857Sobrien PRINT12 (hdr->uid, 0); 250689857Sobrien PRINT12 (hdr->gid, 0); 250789857Sobrien PRINT12 (hdr->mode, 0); 250889857Sobrien PRINT4 (hdr->namlen, 0); 2509130561Sobrien 251089857Sobrien mt = member_table + SIZEOF_AR_HDR_BIG; 251189857Sobrien memcpy (mt, XCOFFARFMAG, SXCOFFARFMAG); 251289857Sobrien mt += SXCOFFARFMAG; 251384865Sobrien 251489857Sobrien PRINT20 (mt, count); 251589857Sobrien mt += XCOFFARMAGBIG_ELEMENT_SIZE; 251689857Sobrien for (i = 0; i < (size_t) count; i++) 251789857Sobrien { 251889857Sobrien PRINT20 (mt, offsets[i]); 251989857Sobrien mt += XCOFFARMAGBIG_ELEMENT_SIZE; 252089857Sobrien } 252184865Sobrien 2522130561Sobrien if (count) 252384865Sobrien { 252489857Sobrien free (offsets); 252589857Sobrien offsets = NULL; 252684865Sobrien } 252789857Sobrien 2528218822Sdim for (current_bfd = abfd->archive_head; 2529218822Sdim current_bfd != NULL; 2530218822Sdim current_bfd = current_bfd->archive_next) 253184865Sobrien { 253284865Sobrien const char *name; 253384865Sobrien size_t namlen; 253484865Sobrien 253589857Sobrien name = normalize_filename (current_bfd); 2536130561Sobrien namlen = sprintf (mt, "%s", name); 253789857Sobrien mt += namlen + 1; 253884865Sobrien } 2539130561Sobrien 254089857Sobrien if (bfd_bwrite (member_table, member_table_size, abfd) != member_table_size) 2541130561Sobrien return FALSE; 254284865Sobrien 254389857Sobrien free (member_table); 254484865Sobrien 254589857Sobrien PRINT20 (fhdr.memoff, nextoff); 254689857Sobrien 254789857Sobrien prevoff = nextoff; 254889857Sobrien nextoff += member_table_size; 254989857Sobrien 255084865Sobrien /* Write out the armap, if appropriate. */ 255184865Sobrien 2552130561Sobrien if (! makemap || ! hasobjects) 255389857Sobrien PRINT20 (fhdr.symoff, 0); 255484865Sobrien else 255584865Sobrien { 255684865Sobrien BFD_ASSERT (nextoff == bfd_tell (abfd)); 255789857Sobrien 255889857Sobrien /* Save nextoff in fhdr.symoff so the armap routine can use it. */ 255989857Sobrien PRINT20 (fhdr.symoff, nextoff); 2560130561Sobrien 256184865Sobrien bfd_ardata (abfd)->tdata = (PTR) &fhdr; 256284865Sobrien if (! _bfd_compute_and_write_armap (abfd, 0)) 2563130561Sobrien return FALSE; 256484865Sobrien } 256584865Sobrien 256684865Sobrien /* Write out the archive file header. */ 256784865Sobrien 256884865Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 2569130561Sobrien || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR_BIG, 257089857Sobrien abfd) != SIZEOF_AR_FILE_HDR_BIG)) 2571130561Sobrien return FALSE; 2572130561Sobrien 2573130561Sobrien return TRUE; 257484865Sobrien} 257584865Sobrien 2576130561Sobrienbfd_boolean 257784865Sobrien_bfd_xcoff_write_archive_contents (abfd) 257884865Sobrien bfd *abfd; 257984865Sobrien{ 258084865Sobrien if (! xcoff_big_format_p (abfd)) 258184865Sobrien return xcoff_write_archive_contents_old (abfd); 258284865Sobrien else 258384865Sobrien return xcoff_write_archive_contents_big (abfd); 258484865Sobrien} 258584865Sobrien 258684865Sobrien/* We can't use the usual coff_sizeof_headers routine, because AIX 258784865Sobrien always uses an a.out header. */ 258884865Sobrien 258984865Sobrienint 2590218822Sdim_bfd_xcoff_sizeof_headers (bfd *abfd, 2591218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 259284865Sobrien{ 259384865Sobrien int size; 259484865Sobrien 259584865Sobrien size = FILHSZ; 259684865Sobrien if (xcoff_data (abfd)->full_aouthdr) 259784865Sobrien size += AOUTSZ; 259884865Sobrien else 259984865Sobrien size += SMALL_AOUTSZ; 260084865Sobrien size += abfd->section_count * SCNHSZ; 260184865Sobrien return size; 260284865Sobrien} 260389857Sobrien 260489857Sobrien/* Routines to swap information in the XCOFF .loader section. If we 260589857Sobrien ever need to write an XCOFF loader, this stuff will need to be 260689857Sobrien moved to another file shared by the linker (which XCOFF calls the 260789857Sobrien ``binder'') and the loader. */ 260889857Sobrien 260989857Sobrien/* Swap in the ldhdr structure. */ 261089857Sobrien 261189857Sobrienstatic void 261289857Sobrienxcoff_swap_ldhdr_in (abfd, s, dst) 261389857Sobrien bfd *abfd; 261489857Sobrien const PTR s; 261589857Sobrien struct internal_ldhdr *dst; 261689857Sobrien{ 261789857Sobrien const struct external_ldhdr *src = (const struct external_ldhdr *) s; 261889857Sobrien 261989857Sobrien dst->l_version = bfd_get_32 (abfd, src->l_version); 262089857Sobrien dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms); 262189857Sobrien dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc); 262289857Sobrien dst->l_istlen = bfd_get_32 (abfd, src->l_istlen); 262389857Sobrien dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid); 262489857Sobrien dst->l_impoff = bfd_get_32 (abfd, src->l_impoff); 262589857Sobrien dst->l_stlen = bfd_get_32 (abfd, src->l_stlen); 262689857Sobrien dst->l_stoff = bfd_get_32 (abfd, src->l_stoff); 262789857Sobrien} 262889857Sobrien 262989857Sobrien/* Swap out the ldhdr structure. */ 263089857Sobrien 263189857Sobrienstatic void 263289857Sobrienxcoff_swap_ldhdr_out (abfd, src, d) 263389857Sobrien bfd *abfd; 263489857Sobrien const struct internal_ldhdr *src; 263589857Sobrien PTR d; 263689857Sobrien{ 263789857Sobrien struct external_ldhdr *dst = (struct external_ldhdr *) d; 263889857Sobrien 263989857Sobrien bfd_put_32 (abfd, (bfd_vma) src->l_version, dst->l_version); 264089857Sobrien bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms); 264189857Sobrien bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc); 264289857Sobrien bfd_put_32 (abfd, src->l_istlen, dst->l_istlen); 264389857Sobrien bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid); 264489857Sobrien bfd_put_32 (abfd, src->l_impoff, dst->l_impoff); 264589857Sobrien bfd_put_32 (abfd, src->l_stlen, dst->l_stlen); 264689857Sobrien bfd_put_32 (abfd, src->l_stoff, dst->l_stoff); 264789857Sobrien} 264889857Sobrien 264989857Sobrien/* Swap in the ldsym structure. */ 265089857Sobrien 265189857Sobrienstatic void 265289857Sobrienxcoff_swap_ldsym_in (abfd, s, dst) 265389857Sobrien bfd *abfd; 265489857Sobrien const PTR s; 265589857Sobrien struct internal_ldsym *dst; 265689857Sobrien{ 265789857Sobrien const struct external_ldsym *src = (const struct external_ldsym *) s; 265889857Sobrien 265989857Sobrien if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0) { 266089857Sobrien memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN); 266189857Sobrien } else { 266289857Sobrien dst->_l._l_l._l_zeroes = 0; 266389857Sobrien dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset); 266489857Sobrien } 266589857Sobrien dst->l_value = bfd_get_32 (abfd, src->l_value); 266689857Sobrien dst->l_scnum = bfd_get_16 (abfd, src->l_scnum); 266789857Sobrien dst->l_smtype = bfd_get_8 (abfd, src->l_smtype); 266889857Sobrien dst->l_smclas = bfd_get_8 (abfd, src->l_smclas); 266989857Sobrien dst->l_ifile = bfd_get_32 (abfd, src->l_ifile); 267089857Sobrien dst->l_parm = bfd_get_32 (abfd, src->l_parm); 267189857Sobrien} 267289857Sobrien 267389857Sobrien/* Swap out the ldsym structure. */ 267489857Sobrien 267589857Sobrienstatic void 267689857Sobrienxcoff_swap_ldsym_out (abfd, src, d) 267789857Sobrien bfd *abfd; 267889857Sobrien const struct internal_ldsym *src; 267989857Sobrien PTR d; 268089857Sobrien{ 268189857Sobrien struct external_ldsym *dst = (struct external_ldsym *) d; 268289857Sobrien 268389857Sobrien if (src->_l._l_l._l_zeroes != 0) 268489857Sobrien memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN); 268589857Sobrien else 268689857Sobrien { 268789857Sobrien bfd_put_32 (abfd, (bfd_vma) 0, dst->_l._l_l._l_zeroes); 268889857Sobrien bfd_put_32 (abfd, (bfd_vma) src->_l._l_l._l_offset, 268989857Sobrien dst->_l._l_l._l_offset); 269089857Sobrien } 269189857Sobrien bfd_put_32 (abfd, src->l_value, dst->l_value); 269289857Sobrien bfd_put_16 (abfd, (bfd_vma) src->l_scnum, dst->l_scnum); 269389857Sobrien bfd_put_8 (abfd, src->l_smtype, dst->l_smtype); 269489857Sobrien bfd_put_8 (abfd, src->l_smclas, dst->l_smclas); 269589857Sobrien bfd_put_32 (abfd, src->l_ifile, dst->l_ifile); 269689857Sobrien bfd_put_32 (abfd, src->l_parm, dst->l_parm); 269789857Sobrien} 269889857Sobrien 2699104834Sobrienstatic void 2700104834Sobrienxcoff_swap_reloc_in (abfd, s, d) 2701104834Sobrien bfd *abfd; 2702104834Sobrien PTR s; 2703104834Sobrien PTR d; 2704104834Sobrien{ 2705104834Sobrien struct external_reloc *src = (struct external_reloc *) s; 2706104834Sobrien struct internal_reloc *dst = (struct internal_reloc *) d; 2707104834Sobrien 2708104834Sobrien memset (dst, 0, sizeof (struct internal_reloc)); 2709104834Sobrien 2710104834Sobrien dst->r_vaddr = bfd_get_32 (abfd, src->r_vaddr); 2711104834Sobrien dst->r_symndx = bfd_get_32 (abfd, src->r_symndx); 2712104834Sobrien dst->r_size = bfd_get_8 (abfd, src->r_size); 2713104834Sobrien dst->r_type = bfd_get_8 (abfd, src->r_type); 2714104834Sobrien} 2715104834Sobrien 2716104834Sobrienstatic unsigned int 2717104834Sobrienxcoff_swap_reloc_out (abfd, s, d) 2718104834Sobrien bfd *abfd; 2719104834Sobrien PTR s; 2720104834Sobrien PTR d; 2721104834Sobrien{ 2722104834Sobrien struct internal_reloc *src = (struct internal_reloc *) s; 2723104834Sobrien struct external_reloc *dst = (struct external_reloc *) d; 2724104834Sobrien 2725104834Sobrien bfd_put_32 (abfd, src->r_vaddr, dst->r_vaddr); 2726104834Sobrien bfd_put_32 (abfd, src->r_symndx, dst->r_symndx); 2727104834Sobrien bfd_put_8 (abfd, src->r_type, dst->r_type); 2728104834Sobrien bfd_put_8 (abfd, src->r_size, dst->r_size); 2729104834Sobrien 2730104834Sobrien return bfd_coff_relsz (abfd); 2731104834Sobrien} 2732104834Sobrien 273389857Sobrien/* Swap in the ldrel structure. */ 273489857Sobrien 273589857Sobrienstatic void 273689857Sobrienxcoff_swap_ldrel_in (abfd, s, dst) 273789857Sobrien bfd *abfd; 273889857Sobrien const PTR s; 273989857Sobrien struct internal_ldrel *dst; 274089857Sobrien{ 274189857Sobrien const struct external_ldrel *src = (const struct external_ldrel *) s; 274289857Sobrien 274389857Sobrien dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr); 274489857Sobrien dst->l_symndx = bfd_get_32 (abfd, src->l_symndx); 274589857Sobrien dst->l_rtype = bfd_get_16 (abfd, src->l_rtype); 274689857Sobrien dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm); 274789857Sobrien} 274889857Sobrien 274989857Sobrien/* Swap out the ldrel structure. */ 275089857Sobrien 275189857Sobrienstatic void 275289857Sobrienxcoff_swap_ldrel_out (abfd, src, d) 275389857Sobrien bfd *abfd; 275489857Sobrien const struct internal_ldrel *src; 275589857Sobrien PTR d; 275689857Sobrien{ 275789857Sobrien struct external_ldrel *dst = (struct external_ldrel *) d; 275889857Sobrien 275989857Sobrien bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr); 276089857Sobrien bfd_put_32 (abfd, src->l_symndx, dst->l_symndx); 276189857Sobrien bfd_put_16 (abfd, (bfd_vma) src->l_rtype, dst->l_rtype); 276289857Sobrien bfd_put_16 (abfd, (bfd_vma) src->l_rsecnm, dst->l_rsecnm); 276389857Sobrien} 276489857Sobrien 276589857Sobrien 2766130561Sobrienbfd_boolean 2767130561Sobrienxcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto, 2768104834Sobrien val, addend, relocation, contents) 2769104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 2770104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2771104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2772104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 2773104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2774104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 2775104834Sobrien bfd_vma val ATTRIBUTE_UNUSED; 2776104834Sobrien bfd_vma addend ATTRIBUTE_UNUSED; 2777104834Sobrien bfd_vma *relocation ATTRIBUTE_UNUSED; 2778104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2779104834Sobrien{ 2780130561Sobrien return TRUE; 2781104834Sobrien} 278289857Sobrien 2783130561Sobrienbfd_boolean 2784130561Sobrienxcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto, 2785104834Sobrien val, addend, relocation, contents) 2786104834Sobrien bfd *input_bfd; 2787104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2788104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2789104834Sobrien struct internal_reloc *rel; 2790104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2791104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 2792104834Sobrien bfd_vma val ATTRIBUTE_UNUSED; 2793104834Sobrien bfd_vma addend ATTRIBUTE_UNUSED; 2794104834Sobrien bfd_vma *relocation ATTRIBUTE_UNUSED; 2795104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2796104834Sobrien{ 2797104834Sobrien (*_bfd_error_handler) 2798104834Sobrien (_("%s: unsupported relocation type 0x%02x"), 2799104834Sobrien bfd_get_filename (input_bfd), (unsigned int) rel->r_type); 2800104834Sobrien bfd_set_error (bfd_error_bad_value); 2801130561Sobrien return FALSE; 2802104834Sobrien} 2803104834Sobrien 2804130561Sobrienbfd_boolean 2805130561Sobrienxcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto, 2806104834Sobrien val, addend, relocation, contents) 2807104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 2808104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2809104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2810104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 2811104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2812104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 2813104834Sobrien bfd_vma val; 2814104834Sobrien bfd_vma addend; 2815104834Sobrien bfd_vma *relocation; 2816104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2817104834Sobrien{ 2818104834Sobrien *relocation = val + addend; 2819130561Sobrien return TRUE; 2820104834Sobrien} 2821104834Sobrien 2822130561Sobrienbfd_boolean 2823130561Sobrienxcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto, 2824104834Sobrien val, addend, relocation, contents) 2825104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 2826104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2827104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2828104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 2829104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2830104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 2831104834Sobrien bfd_vma val; 2832104834Sobrien bfd_vma addend; 2833104834Sobrien bfd_vma *relocation; 2834104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2835104834Sobrien{ 2836104834Sobrien *relocation = addend - val; 2837130561Sobrien return TRUE; 2838104834Sobrien} 2839104834Sobrien 2840130561Sobrienbfd_boolean 2841130561Sobrienxcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto, 2842104834Sobrien val, addend, relocation, contents) 2843104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 2844104834Sobrien asection *input_section; 2845104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2846104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 2847104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2848104834Sobrien struct reloc_howto_struct *howto; 2849104834Sobrien bfd_vma val; 2850104834Sobrien bfd_vma addend; 2851104834Sobrien bfd_vma *relocation; 2852104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2853104834Sobrien{ 2854130561Sobrien howto->pc_relative = TRUE; 2855104834Sobrien 2856104834Sobrien /* A PC relative reloc includes the section address. */ 2857104834Sobrien addend += input_section->vma; 2858104834Sobrien 2859104834Sobrien *relocation = val + addend; 2860104834Sobrien *relocation -= (input_section->output_section->vma 2861104834Sobrien + input_section->output_offset); 2862130561Sobrien return TRUE; 2863104834Sobrien} 2864104834Sobrien 2865130561Sobrienbfd_boolean 2866130561Sobrienxcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto, 2867104834Sobrien val, addend, relocation, contents) 2868104834Sobrien bfd *input_bfd; 2869104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2870104834Sobrien bfd *output_bfd; 2871104834Sobrien struct internal_reloc *rel; 2872104834Sobrien struct internal_syment *sym; 2873104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 2874104834Sobrien bfd_vma val; 2875104834Sobrien bfd_vma addend ATTRIBUTE_UNUSED; 2876104834Sobrien bfd_vma *relocation; 2877104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2878104834Sobrien{ 2879104834Sobrien struct xcoff_link_hash_entry *h; 2880104834Sobrien 2881130561Sobrien if (0 > rel->r_symndx) 2882130561Sobrien return FALSE; 2883104834Sobrien 2884104834Sobrien h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx]; 2885104834Sobrien 2886104834Sobrien if (h != NULL && h->smclas != XMC_TD) 2887104834Sobrien { 2888104834Sobrien if (h->toc_section == NULL) 2889104834Sobrien { 2890104834Sobrien (*_bfd_error_handler) 2891104834Sobrien (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"), 2892104834Sobrien bfd_get_filename (input_bfd), rel->r_vaddr, 2893104834Sobrien h->root.root.string); 2894104834Sobrien bfd_set_error (bfd_error_bad_value); 2895130561Sobrien return FALSE; 2896104834Sobrien } 2897130561Sobrien 2898104834Sobrien BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0); 2899104834Sobrien val = (h->toc_section->output_section->vma 2900104834Sobrien + h->toc_section->output_offset); 2901104834Sobrien } 2902130561Sobrien 2903104834Sobrien *relocation = ((val - xcoff_data (output_bfd)->toc) 2904104834Sobrien - (sym->n_value - xcoff_data (input_bfd)->toc)); 2905130561Sobrien return TRUE; 2906104834Sobrien} 2907104834Sobrien 2908130561Sobrienbfd_boolean 2909130561Sobrienxcoff_reloc_type_ba (input_bfd, input_section, output_bfd, rel, sym, howto, 2910104834Sobrien val, addend, relocation, contents) 2911104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 2912104834Sobrien asection *input_section ATTRIBUTE_UNUSED; 2913104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2914104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 2915104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2916104834Sobrien struct reloc_howto_struct *howto; 2917104834Sobrien bfd_vma val; 2918104834Sobrien bfd_vma addend; 2919104834Sobrien bfd_vma *relocation; 2920104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2921104834Sobrien{ 2922104834Sobrien howto->src_mask &= ~3; 2923104834Sobrien howto->dst_mask = howto->src_mask; 2924104834Sobrien 2925104834Sobrien *relocation = val + addend; 2926104834Sobrien 2927130561Sobrien return TRUE; 2928104834Sobrien} 2929104834Sobrien 2930130561Sobrienstatic bfd_boolean 2931130561Sobrienxcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, 2932104834Sobrien val, addend, relocation, contents) 2933104834Sobrien bfd *input_bfd; 2934104834Sobrien asection *input_section; 2935104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 2936104834Sobrien struct internal_reloc *rel; 2937104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 2938104834Sobrien struct reloc_howto_struct *howto; 2939104834Sobrien bfd_vma val; 2940104834Sobrien bfd_vma addend; 2941104834Sobrien bfd_vma *relocation; 2942104834Sobrien bfd_byte *contents; 2943104834Sobrien{ 2944104834Sobrien struct xcoff_link_hash_entry *h; 2945104834Sobrien 2946130561Sobrien if (0 > rel->r_symndx) 2947130561Sobrien return FALSE; 2948104834Sobrien 2949104834Sobrien h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx]; 2950104834Sobrien 2951104834Sobrien /* If we see an R_BR or R_RBR reloc which is jumping to global 2952104834Sobrien linkage code, and it is followed by an appropriate cror nop 2953104834Sobrien instruction, we replace the cror with lwz r2,20(r1). This 2954104834Sobrien restores the TOC after the glink code. Contrariwise, if the 2955104834Sobrien call is followed by a lwz r2,20(r1), but the call is not 2956104834Sobrien going to global linkage code, we can replace the load with a 2957104834Sobrien cror. */ 2958130561Sobrien if (NULL != h 2959130561Sobrien && bfd_link_hash_defined == h->root.type 2960218822Sdim && rel->r_vaddr - input_section->vma + 8 <= input_section->size) 2961104834Sobrien { 2962104834Sobrien bfd_byte *pnext; 2963104834Sobrien unsigned long next; 2964130561Sobrien 2965104834Sobrien pnext = contents + (rel->r_vaddr - input_section->vma) + 4; 2966104834Sobrien next = bfd_get_32 (input_bfd, pnext); 2967130561Sobrien 2968104834Sobrien /* The _ptrgl function is magic. It is used by the AIX 2969104834Sobrien compiler to call a function through a pointer. */ 2970104834Sobrien if (h->smclas == XMC_GL || strcmp (h->root.root.string, "._ptrgl") == 0) 2971104834Sobrien { 2972130561Sobrien if (next == 0x4def7b82 /* cror 15,15,15 */ 2973130561Sobrien || next == 0x4ffffb82 /* cror 31,31,31 */ 2974130561Sobrien || next == 0x60000000) /* ori r0,r0,0 */ 2975130561Sobrien bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */ 2976130561Sobrien 2977104834Sobrien } 2978104834Sobrien else 2979130561Sobrien { 2980130561Sobrien if (next == 0x80410014) /* lwz r1,20(r1) */ 2981130561Sobrien bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */ 2982130561Sobrien } 2983130561Sobrien } 2984130561Sobrien else if (NULL != h && bfd_link_hash_undefined == h->root.type) 2985104834Sobrien { 2986104834Sobrien /* Normally, this relocation is against a defined symbol. In the 2987104834Sobrien case where this is a partial link and the output section offset 2988130561Sobrien is greater than 2^25, the linker will return an invalid error 2989104834Sobrien message that the relocation has been truncated. Yes it has been 2990130561Sobrien truncated but no it not important. For this case, disable the 2991104834Sobrien overflow checking. */ 2992130561Sobrien 2993104834Sobrien howto->complain_on_overflow = complain_overflow_dont; 2994104834Sobrien } 2995130561Sobrien 2996130561Sobrien howto->pc_relative = TRUE; 2997104834Sobrien howto->src_mask &= ~3; 2998104834Sobrien howto->dst_mask = howto->src_mask; 2999104834Sobrien 3000104834Sobrien /* A PC relative reloc includes the section address. */ 3001104834Sobrien addend += input_section->vma; 3002130561Sobrien 3003104834Sobrien *relocation = val + addend; 3004104834Sobrien *relocation -= (input_section->output_section->vma 3005104834Sobrien + input_section->output_offset); 3006130561Sobrien return TRUE; 3007104834Sobrien} 3008104834Sobrien 3009130561Sobrienbfd_boolean 3010130561Sobrienxcoff_reloc_type_crel (input_bfd, input_section, output_bfd, rel, sym, howto, 3011104834Sobrien val, addend, relocation, contents) 3012104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 3013104834Sobrien asection *input_section; 3014104834Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 3015104834Sobrien struct internal_reloc *rel ATTRIBUTE_UNUSED; 3016104834Sobrien struct internal_syment *sym ATTRIBUTE_UNUSED; 3017104834Sobrien struct reloc_howto_struct *howto; 3018104834Sobrien bfd_vma val ATTRIBUTE_UNUSED; 3019104834Sobrien bfd_vma addend; 3020104834Sobrien bfd_vma *relocation; 3021104834Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 3022104834Sobrien{ 3023130561Sobrien howto->pc_relative = TRUE; 3024104834Sobrien howto->src_mask &= ~3; 3025104834Sobrien howto->dst_mask = howto->src_mask; 3026104834Sobrien 3027104834Sobrien /* A PC relative reloc includes the section address. */ 3028104834Sobrien addend += input_section->vma; 3029104834Sobrien 3030104834Sobrien *relocation = val + addend; 3031104834Sobrien *relocation -= (input_section->output_section->vma 3032104834Sobrien + input_section->output_offset); 3033130561Sobrien return TRUE; 3034104834Sobrien} 3035104834Sobrien 3036130561Sobrienstatic bfd_boolean 3037130561Sobrienxcoff_complain_overflow_dont_func (input_bfd, val, relocation, howto) 3038104834Sobrien bfd *input_bfd ATTRIBUTE_UNUSED; 3039104834Sobrien bfd_vma val ATTRIBUTE_UNUSED; 3040104834Sobrien bfd_vma relocation ATTRIBUTE_UNUSED; 3041104834Sobrien struct reloc_howto_struct *howto ATTRIBUTE_UNUSED; 3042104834Sobrien{ 3043130561Sobrien return FALSE; 3044104834Sobrien} 3045104834Sobrien 3046130561Sobrienstatic bfd_boolean 3047130561Sobrienxcoff_complain_overflow_bitfield_func (input_bfd, val, relocation, howto) 3048104834Sobrien bfd *input_bfd; 3049104834Sobrien bfd_vma val; 3050104834Sobrien bfd_vma relocation; 3051130561Sobrien struct reloc_howto_struct *howto; 3052104834Sobrien{ 3053104834Sobrien bfd_vma addrmask, fieldmask, signmask, ss; 3054104834Sobrien bfd_vma a, b, sum; 3055130561Sobrien 3056104834Sobrien /* Get the values to be added together. For signed and unsigned 3057104834Sobrien relocations, we assume that all values should be truncated to 3058104834Sobrien the size of an address. For bitfields, all the bits matter. 3059104834Sobrien See also bfd_check_overflow. */ 3060104834Sobrien fieldmask = N_ONES (howto->bitsize); 3061104834Sobrien addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask; 3062104834Sobrien a = relocation; 3063104834Sobrien b = val & howto->src_mask; 3064104834Sobrien 3065104834Sobrien /* Much like unsigned, except no trimming with addrmask. In 3066104834Sobrien addition, the sum overflows if there is a carry out of 3067104834Sobrien the bfd_vma, i.e., the sum is less than either input 3068104834Sobrien operand. */ 3069104834Sobrien a >>= howto->rightshift; 3070104834Sobrien b >>= howto->bitpos; 3071130561Sobrien 3072104834Sobrien /* Bitfields are sometimes used for signed numbers; for 3073104834Sobrien example, a 13-bit field sometimes represents values in 3074104834Sobrien 0..8191 and sometimes represents values in -4096..4095. 3075104834Sobrien If the field is signed and a is -4095 (0x1001) and b is 3076104834Sobrien -1 (0x1fff), the sum is -4096 (0x1000), but (0x1001 + 3077104834Sobrien 0x1fff is 0x3000). It's not clear how to handle this 3078104834Sobrien everywhere, since there is not way to know how many bits 3079104834Sobrien are significant in the relocation, but the original code 3080104834Sobrien assumed that it was fully sign extended, and we will keep 3081104834Sobrien that assumption. */ 3082104834Sobrien signmask = (fieldmask >> 1) + 1; 3083130561Sobrien 3084104834Sobrien if ((a & ~ fieldmask) != 0) 3085104834Sobrien { 3086104834Sobrien /* Some bits out of the field are set. This might not 3087104834Sobrien be a problem: if this is a signed bitfield, it is OK 3088104834Sobrien iff all the high bits are set, including the sign 3089104834Sobrien bit. We'll try setting all but the most significant 3090104834Sobrien bit in the original relocation value: if this is all 3091104834Sobrien ones, we are OK, assuming a signed bitfield. */ 3092104834Sobrien ss = (signmask << howto->rightshift) - 1; 3093104834Sobrien if ((ss | relocation) != ~ (bfd_vma) 0) 3094130561Sobrien return TRUE; 3095104834Sobrien a &= fieldmask; 3096104834Sobrien } 3097130561Sobrien 3098104834Sobrien /* We just assume (b & ~ fieldmask) == 0. */ 3099130561Sobrien 3100104834Sobrien /* We explicitly permit wrap around if this relocation 3101104834Sobrien covers the high bit of an address. The Linux kernel 3102104834Sobrien relies on it, and it is the only way to write assembler 3103104834Sobrien code which can run when loaded at a location 0x80000000 3104104834Sobrien away from the location at which it is linked. */ 3105104834Sobrien if (howto->bitsize + howto->rightshift 3106104834Sobrien == bfd_arch_bits_per_address (input_bfd)) 3107130561Sobrien return FALSE; 3108130561Sobrien 3109104834Sobrien sum = a + b; 3110104834Sobrien if (sum < a || (sum & ~ fieldmask) != 0) 3111104834Sobrien { 3112104834Sobrien /* There was a carry out, or the field overflow. Test 3113104834Sobrien for signed operands again. Here is the overflow test 3114104834Sobrien is as for complain_overflow_signed. */ 3115104834Sobrien if (((~ (a ^ b)) & (a ^ sum)) & signmask) 3116130561Sobrien return TRUE; 3117104834Sobrien } 3118130561Sobrien 3119130561Sobrien return FALSE; 3120104834Sobrien} 3121104834Sobrien 3122130561Sobrienstatic bfd_boolean 3123130561Sobrienxcoff_complain_overflow_signed_func (input_bfd, val, relocation, howto) 3124104834Sobrien bfd *input_bfd; 3125104834Sobrien bfd_vma val; 3126104834Sobrien bfd_vma relocation; 3127104834Sobrien struct reloc_howto_struct *howto; 3128104834Sobrien{ 3129104834Sobrien bfd_vma addrmask, fieldmask, signmask, ss; 3130104834Sobrien bfd_vma a, b, sum; 3131130561Sobrien 3132104834Sobrien /* Get the values to be added together. For signed and unsigned 3133104834Sobrien relocations, we assume that all values should be truncated to 3134104834Sobrien the size of an address. For bitfields, all the bits matter. 3135104834Sobrien See also bfd_check_overflow. */ 3136104834Sobrien fieldmask = N_ONES (howto->bitsize); 3137104834Sobrien addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask; 3138104834Sobrien a = relocation; 3139104834Sobrien b = val & howto->src_mask; 3140104834Sobrien 3141104834Sobrien a = (a & addrmask) >> howto->rightshift; 3142130561Sobrien 3143104834Sobrien /* If any sign bits are set, all sign bits must be set. 3144104834Sobrien That is, A must be a valid negative address after 3145104834Sobrien shifting. */ 3146104834Sobrien signmask = ~ (fieldmask >> 1); 3147104834Sobrien ss = a & signmask; 3148104834Sobrien if (ss != 0 && ss != ((addrmask >> howto->rightshift) & signmask)) 3149130561Sobrien return TRUE; 3150130561Sobrien 3151104834Sobrien /* We only need this next bit of code if the sign bit of B 3152104834Sobrien is below the sign bit of A. This would only happen if 3153104834Sobrien SRC_MASK had fewer bits than BITSIZE. Note that if 3154104834Sobrien SRC_MASK has more bits than BITSIZE, we can get into 3155104834Sobrien trouble; we would need to verify that B is in range, as 3156104834Sobrien we do for A above. */ 3157104834Sobrien signmask = ((~ howto->src_mask) >> 1) & howto->src_mask; 3158104834Sobrien if ((b & signmask) != 0) 3159104834Sobrien { 3160104834Sobrien /* Set all the bits above the sign bit. */ 3161104834Sobrien b -= signmask <<= 1; 3162104834Sobrien } 3163130561Sobrien 3164104834Sobrien b = (b & addrmask) >> howto->bitpos; 3165130561Sobrien 3166104834Sobrien /* Now we can do the addition. */ 3167104834Sobrien sum = a + b; 3168130561Sobrien 3169104834Sobrien /* See if the result has the correct sign. Bits above the 3170104834Sobrien sign bit are junk now; ignore them. If the sum is 3171104834Sobrien positive, make sure we did not have all negative inputs; 3172104834Sobrien if the sum is negative, make sure we did not have all 3173104834Sobrien positive inputs. The test below looks only at the sign 3174104834Sobrien bits, and it really just 3175104834Sobrien SIGN (A) == SIGN (B) && SIGN (A) != SIGN (SUM) 3176104834Sobrien */ 3177104834Sobrien signmask = (fieldmask >> 1) + 1; 3178104834Sobrien if (((~ (a ^ b)) & (a ^ sum)) & signmask) 3179130561Sobrien return TRUE; 3180130561Sobrien 3181130561Sobrien return FALSE; 3182104834Sobrien} 3183104834Sobrien 3184130561Sobrienstatic bfd_boolean 3185130561Sobrienxcoff_complain_overflow_unsigned_func (input_bfd, val, relocation, howto) 3186104834Sobrien bfd *input_bfd; 3187104834Sobrien bfd_vma val; 3188104834Sobrien bfd_vma relocation; 3189130561Sobrien struct reloc_howto_struct *howto; 3190104834Sobrien{ 3191104834Sobrien bfd_vma addrmask, fieldmask; 3192104834Sobrien bfd_vma a, b, sum; 3193130561Sobrien 3194104834Sobrien /* Get the values to be added together. For signed and unsigned 3195104834Sobrien relocations, we assume that all values should be truncated to 3196104834Sobrien the size of an address. For bitfields, all the bits matter. 3197104834Sobrien See also bfd_check_overflow. */ 3198104834Sobrien fieldmask = N_ONES (howto->bitsize); 3199104834Sobrien addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask; 3200104834Sobrien a = relocation; 3201104834Sobrien b = val & howto->src_mask; 3202104834Sobrien 3203104834Sobrien /* Checking for an unsigned overflow is relatively easy: 3204104834Sobrien trim the addresses and add, and trim the result as well. 3205104834Sobrien Overflow is normally indicated when the result does not 3206104834Sobrien fit in the field. However, we also need to consider the 3207104834Sobrien case when, e.g., fieldmask is 0x7fffffff or smaller, an 3208104834Sobrien input is 0x80000000, and bfd_vma is only 32 bits; then we 3209104834Sobrien will get sum == 0, but there is an overflow, since the 3210104834Sobrien inputs did not fit in the field. Instead of doing a 3211104834Sobrien separate test, we can check for this by or-ing in the 3212104834Sobrien operands when testing for the sum overflowing its final 3213104834Sobrien field. */ 3214104834Sobrien a = (a & addrmask) >> howto->rightshift; 3215104834Sobrien b = (b & addrmask) >> howto->bitpos; 3216104834Sobrien sum = (a + b) & addrmask; 3217104834Sobrien if ((a | b | sum) & ~ fieldmask) 3218130561Sobrien return TRUE; 3219130561Sobrien 3220130561Sobrien return FALSE; 3221104834Sobrien} 3222104834Sobrien 322389857Sobrien/* This is the relocation function for the RS/6000/POWER/PowerPC. 322489857Sobrien This is currently the only processor which uses XCOFF; I hope that 3225130561Sobrien will never change. 322689857Sobrien 3227104834Sobrien I took the relocation type definitions from two documents: 3228104834Sobrien the PowerPC AIX Version 4 Application Binary Interface, First 3229104834Sobrien Edition (April 1992), and the PowerOpen ABI, Big-Endian 3230104834Sobrien 32-Bit Hardware Implementation (June 30, 1994). Differences 3231130561Sobrien between the documents are noted below. 3232104834Sobrien 3233130561Sobrien Unsupported r_type's 3234104834Sobrien 3235104834Sobrien R_RTB: 3236104834Sobrien R_RRTBI: 3237104834Sobrien R_RRTBA: 3238130561Sobrien 3239104834Sobrien These relocs are defined by the PowerPC ABI to be 3240104834Sobrien relative branches which use half of the difference 3241104834Sobrien between the symbol and the program counter. I can't 3242104834Sobrien quite figure out when this is useful. These relocs are 3243130561Sobrien not defined by the PowerOpen ABI. 3244104834Sobrien 3245104834Sobrien Supported r_type's 3246104834Sobrien 3247104834Sobrien R_POS: 3248104834Sobrien Simple positive relocation. 3249104834Sobrien 3250104834Sobrien R_NEG: 3251130561Sobrien Simple negative relocation. 3252104834Sobrien 3253104834Sobrien R_REL: 3254104834Sobrien Simple PC relative relocation. 3255104834Sobrien 3256104834Sobrien R_TOC: 3257104834Sobrien TOC relative relocation. The value in the instruction in 3258104834Sobrien the input file is the offset from the input file TOC to 3259104834Sobrien the desired location. We want the offset from the final 3260104834Sobrien TOC to the desired location. We have: 3261104834Sobrien isym = iTOC + in 3262104834Sobrien iinsn = in + o 3263104834Sobrien osym = oTOC + on 3264104834Sobrien oinsn = on + o 3265104834Sobrien so we must change insn by on - in. 3266104834Sobrien 3267104834Sobrien R_GL: 3268104834Sobrien GL linkage relocation. The value of this relocation 3269130561Sobrien is the address of the entry in the TOC section. 3270104834Sobrien 3271104834Sobrien R_TCL: 3272104834Sobrien Local object TOC address. I can't figure out the 3273130561Sobrien difference between this and case R_GL. 3274104834Sobrien 3275104834Sobrien R_TRL: 3276104834Sobrien TOC relative relocation. A TOC relative load instruction 3277104834Sobrien which may be changed to a load address instruction. 3278130561Sobrien FIXME: We don't currently implement this optimization. 3279104834Sobrien 3280104834Sobrien R_TRLA: 3281104834Sobrien TOC relative relocation. This is a TOC relative load 3282104834Sobrien address instruction which may be changed to a load 3283104834Sobrien instruction. FIXME: I don't know if this is the correct 3284104834Sobrien implementation. 3285104834Sobrien 3286104834Sobrien R_BA: 3287104834Sobrien Absolute branch. We don't want to mess with the lower 3288130561Sobrien two bits of the instruction. 3289104834Sobrien 3290104834Sobrien R_CAI: 3291104834Sobrien The PowerPC ABI defines this as an absolute call which 3292104834Sobrien may be modified to become a relative call. The PowerOpen 3293130561Sobrien ABI does not define this relocation type. 3294130561Sobrien 3295104834Sobrien R_RBA: 3296104834Sobrien Absolute branch which may be modified to become a 3297130561Sobrien relative branch. 3298104834Sobrien 3299104834Sobrien R_RBAC: 3300104834Sobrien The PowerPC ABI defines this as an absolute branch to a 3301104834Sobrien fixed address which may be modified to an absolute branch 3302104834Sobrien to a symbol. The PowerOpen ABI does not define this 3303130561Sobrien relocation type. 3304104834Sobrien 3305104834Sobrien R_RBRC: 3306104834Sobrien The PowerPC ABI defines this as an absolute branch to a 3307104834Sobrien fixed address which may be modified to a relative branch. 3308130561Sobrien The PowerOpen ABI does not define this relocation type. 3309104834Sobrien 3310104834Sobrien R_BR: 3311104834Sobrien Relative branch. We don't want to mess with the lower 3312130561Sobrien two bits of the instruction. 3313104834Sobrien 3314104834Sobrien R_CREL: 3315104834Sobrien The PowerPC ABI defines this as a relative call which may 3316104834Sobrien be modified to become an absolute call. The PowerOpen 3317130561Sobrien ABI does not define this relocation type. 3318104834Sobrien 3319104834Sobrien R_RBR: 3320104834Sobrien A relative branch which may be modified to become an 3321104834Sobrien absolute branch. FIXME: We don't implement this, 3322104834Sobrien although we should for symbols of storage mapping class 3323130561Sobrien XMC_XO. 3324104834Sobrien 3325104834Sobrien R_RL: 3326104834Sobrien The PowerPC AIX ABI describes this as a load which may be 3327104834Sobrien changed to a load address. The PowerOpen ABI says this 3328130561Sobrien is the same as case R_POS. 3329104834Sobrien 3330104834Sobrien R_RLA: 3331104834Sobrien The PowerPC AIX ABI describes this as a load address 3332104834Sobrien which may be changed to a load. The PowerOpen ABI says 3333130561Sobrien this is the same as R_POS. 3334104834Sobrien*/ 3335104834Sobrien 3336130561Sobrienbfd_boolean 333789857Sobrienxcoff_ppc_relocate_section (output_bfd, info, input_bfd, 333889857Sobrien input_section, contents, relocs, syms, 333989857Sobrien sections) 334089857Sobrien bfd *output_bfd; 334189857Sobrien struct bfd_link_info *info; 334289857Sobrien bfd *input_bfd; 334389857Sobrien asection *input_section; 334489857Sobrien bfd_byte *contents; 334589857Sobrien struct internal_reloc *relocs; 334689857Sobrien struct internal_syment *syms; 334789857Sobrien asection **sections; 334889857Sobrien{ 334989857Sobrien struct internal_reloc *rel; 335089857Sobrien struct internal_reloc *relend; 335189857Sobrien 335289857Sobrien rel = relocs; 335389857Sobrien relend = rel + input_section->reloc_count; 335489857Sobrien for (; rel < relend; rel++) 335589857Sobrien { 335689857Sobrien long symndx; 335789857Sobrien struct xcoff_link_hash_entry *h; 335889857Sobrien struct internal_syment *sym; 335989857Sobrien bfd_vma addend; 336089857Sobrien bfd_vma val; 336189857Sobrien struct reloc_howto_struct howto; 3362104834Sobrien bfd_vma relocation; 3363104834Sobrien bfd_vma value_to_relocate; 3364104834Sobrien bfd_vma address; 3365104834Sobrien bfd_byte *location; 336689857Sobrien 336789857Sobrien /* Relocation type R_REF is a special relocation type which is 3368130561Sobrien merely used to prevent garbage collection from occurring for 3369130561Sobrien the csect including the symbol which it references. */ 337089857Sobrien if (rel->r_type == R_REF) 337189857Sobrien continue; 337289857Sobrien 3373104834Sobrien /* howto */ 337489857Sobrien howto.type = rel->r_type; 337589857Sobrien howto.rightshift = 0; 337689857Sobrien howto.bitsize = (rel->r_size & 0x1f) + 1; 3377104834Sobrien howto.size = howto.bitsize > 16 ? 2 : 1; 3378130561Sobrien howto.pc_relative = FALSE; 337989857Sobrien howto.bitpos = 0; 3380104834Sobrien howto.complain_on_overflow = (rel->r_size & 0x80 3381104834Sobrien ? complain_overflow_signed 3382104834Sobrien : complain_overflow_bitfield); 338389857Sobrien howto.special_function = NULL; 338489857Sobrien howto.name = "internal"; 3385130561Sobrien howto.partial_inplace = TRUE; 3386130561Sobrien howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize); 3387130561Sobrien howto.pcrel_offset = FALSE; 338889857Sobrien 3389104834Sobrien /* symbol */ 339089857Sobrien val = 0; 3391104834Sobrien addend = 0; 3392104834Sobrien h = NULL; 3393104834Sobrien sym = NULL; 3394130561Sobrien symndx = rel->r_symndx; 339589857Sobrien 3396130561Sobrien if (-1 != symndx) 339789857Sobrien { 339889857Sobrien asection *sec; 3399130561Sobrien 3400104834Sobrien h = obj_xcoff_sym_hashes (input_bfd)[symndx]; 3401104834Sobrien sym = syms + symndx; 3402104834Sobrien addend = - sym->n_value; 3403130561Sobrien 3404130561Sobrien if (NULL == h) 340589857Sobrien { 340689857Sobrien sec = sections[symndx]; 340789857Sobrien /* Hack to make sure we use the right TOC anchor value 3408104834Sobrien if this reloc is against the TOC anchor. */ 340989857Sobrien if (sec->name[3] == '0' 3410104834Sobrien && strcmp (sec->name, ".tc0") == 0) 3411104834Sobrien val = xcoff_data (output_bfd)->toc; 341289857Sobrien else 3413104834Sobrien val = (sec->output_section->vma 3414104834Sobrien + sec->output_offset 3415104834Sobrien + sym->n_value 3416104834Sobrien - sec->vma); 3417130561Sobrien } 3418130561Sobrien else 3419104834Sobrien { 3420130561Sobrien if (h->root.type == bfd_link_hash_defined 3421130561Sobrien || h->root.type == bfd_link_hash_defweak) 342289857Sobrien { 3423104834Sobrien sec = h->root.u.def.section; 3424104834Sobrien val = (h->root.u.def.value 3425104834Sobrien + sec->output_section->vma 3426104834Sobrien + sec->output_offset); 3427130561Sobrien } 3428130561Sobrien else if (h->root.type == bfd_link_hash_common) 3429104834Sobrien { 3430104834Sobrien sec = h->root.u.c.p->section; 343189857Sobrien val = (sec->output_section->vma 3432104834Sobrien + sec->output_offset); 3433130561Sobrien 3434130561Sobrien } 3435130561Sobrien else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT))) 3436130561Sobrien && ! info->relocatable) 3437104834Sobrien { 3438104834Sobrien if (! ((*info->callbacks->undefined_symbol) 3439104834Sobrien (info, h->root.root.string, input_bfd, input_section, 3440130561Sobrien rel->r_vaddr - input_section->vma, TRUE))) 3441130561Sobrien return FALSE; 3442130561Sobrien 3443104834Sobrien /* Don't try to process the reloc. It can't help, and 3444104834Sobrien it may generate another error. */ 3445104834Sobrien continue; 344689857Sobrien } 344789857Sobrien } 344889857Sobrien } 344989857Sobrien 3450130561Sobrien if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION 3451104834Sobrien || !((*xcoff_calculate_relocation[rel->r_type]) 3452130561Sobrien (input_bfd, input_section, output_bfd, rel, sym, &howto, val, 3453130561Sobrien addend, &relocation, contents))) 3454130561Sobrien return FALSE; 3455130561Sobrien 3456104834Sobrien /* address */ 3457104834Sobrien address = rel->r_vaddr - input_section->vma; 3458104834Sobrien location = contents + address; 3459130561Sobrien 3460218822Sdim if (address > input_section->size) 3461130561Sobrien abort (); 346289857Sobrien 3463104834Sobrien /* Get the value we are going to relocate. */ 3464104834Sobrien if (1 == howto.size) 3465104834Sobrien value_to_relocate = bfd_get_16 (input_bfd, location); 3466130561Sobrien else 3467104834Sobrien value_to_relocate = bfd_get_32 (input_bfd, location); 3468130561Sobrien 3469130561Sobrien /* overflow. 3470130561Sobrien 3471104834Sobrien FIXME: We may drop bits during the addition 3472104834Sobrien which we don't check for. We must either check at every single 3473104834Sobrien operation, which would be tedious, or we must do the computations 3474104834Sobrien in a type larger than bfd_vma, which would be inefficient. */ 3475130561Sobrien 3476104834Sobrien if ((unsigned int) howto.complain_on_overflow 3477104834Sobrien >= XCOFF_MAX_COMPLAIN_OVERFLOW) 3478130561Sobrien abort (); 347989857Sobrien 3480104834Sobrien if (((*xcoff_complain_overflow[howto.complain_on_overflow]) 3481130561Sobrien (input_bfd, value_to_relocate, relocation, &howto))) 348289857Sobrien { 3483104834Sobrien const char *name; 3484104834Sobrien char buf[SYMNMLEN + 1]; 3485104834Sobrien char reloc_type_name[10]; 3486130561Sobrien 3487130561Sobrien if (symndx == -1) 348889857Sobrien { 3489104834Sobrien name = "*ABS*"; 3490130561Sobrien } 3491130561Sobrien else if (h != NULL) 349289857Sobrien { 3493218822Sdim name = NULL; 3494130561Sobrien } 3495130561Sobrien else 349689857Sobrien { 3497104834Sobrien name = _bfd_coff_internal_syment_name (input_bfd, sym, buf); 3498104834Sobrien if (name == NULL) 3499104834Sobrien name = "UNKNOWN"; 350089857Sobrien } 3501104834Sobrien sprintf (reloc_type_name, "0x%02x", rel->r_type); 3502130561Sobrien 3503104834Sobrien if (! ((*info->callbacks->reloc_overflow) 3504218822Sdim (info, (h ? &h->root : NULL), name, reloc_type_name, 3505218822Sdim (bfd_vma) 0, input_bfd, input_section, 3506218822Sdim rel->r_vaddr - input_section->vma))) 3507130561Sobrien return FALSE; 350889857Sobrien } 3509130561Sobrien 3510104834Sobrien /* Add RELOCATION to the right bits of VALUE_TO_RELOCATE. */ 3511104834Sobrien value_to_relocate = ((value_to_relocate & ~howto.dst_mask) 3512104834Sobrien | (((value_to_relocate & howto.src_mask) 3513104834Sobrien + relocation) & howto.dst_mask)); 3514130561Sobrien 3515104834Sobrien /* Put the value back in the object file. */ 3516104834Sobrien if (1 == howto.size) 3517104834Sobrien bfd_put_16 (input_bfd, value_to_relocate, location); 3518130561Sobrien else 3519104834Sobrien bfd_put_32 (input_bfd, value_to_relocate, location); 352089857Sobrien } 352189857Sobrien 3522130561Sobrien return TRUE; 352389857Sobrien} 352489857Sobrien 3525130561Sobrienstatic bfd_boolean 352689857Sobrien_bfd_xcoff_put_ldsymbol_name (abfd, ldinfo, ldsym, name) 352789857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 352889857Sobrien struct xcoff_loader_info *ldinfo; 352989857Sobrien struct internal_ldsym *ldsym; 353089857Sobrien const char *name; 353189857Sobrien{ 353289857Sobrien size_t len; 353389857Sobrien len = strlen (name); 353489857Sobrien 353589857Sobrien if (len <= SYMNMLEN) 353689857Sobrien strncpy (ldsym->_l._l_name, name, SYMNMLEN); 353789857Sobrien else 353889857Sobrien { 353989857Sobrien if (ldinfo->string_size + len + 3 > ldinfo->string_alc) 354089857Sobrien { 354189857Sobrien bfd_size_type newalc; 3542218822Sdim char *newstrings; 354389857Sobrien 354489857Sobrien newalc = ldinfo->string_alc * 2; 354589857Sobrien if (newalc == 0) 354689857Sobrien newalc = 32; 354789857Sobrien while (ldinfo->string_size + len + 3 > newalc) 354889857Sobrien newalc *= 2; 354989857Sobrien 3550218822Sdim newstrings = bfd_realloc (ldinfo->strings, newalc); 355189857Sobrien if (newstrings == NULL) 355289857Sobrien { 3553130561Sobrien ldinfo->failed = TRUE; 3554130561Sobrien return FALSE; 355589857Sobrien } 355689857Sobrien ldinfo->string_alc = newalc; 355789857Sobrien ldinfo->strings = newstrings; 355889857Sobrien } 355989857Sobrien 356089857Sobrien bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1), 356189857Sobrien ldinfo->strings + ldinfo->string_size); 356289857Sobrien strcpy (ldinfo->strings + ldinfo->string_size + 2, name); 356389857Sobrien ldsym->_l._l_l._l_zeroes = 0; 356489857Sobrien ldsym->_l._l_l._l_offset = ldinfo->string_size + 2; 356589857Sobrien ldinfo->string_size += len + 3; 356689857Sobrien } 356789857Sobrien 3568130561Sobrien return TRUE; 356989857Sobrien} 357089857Sobrien 3571130561Sobrienstatic bfd_boolean 357289857Sobrien_bfd_xcoff_put_symbol_name (bfd *abfd, struct bfd_strtab_hash *strtab, 357389857Sobrien struct internal_syment *sym, 357489857Sobrien const char *name) 357589857Sobrien{ 357689857Sobrien if (strlen (name) <= SYMNMLEN) 357789857Sobrien { 357889857Sobrien strncpy (sym->_n._n_name, name, SYMNMLEN); 357989857Sobrien } 358089857Sobrien else 358189857Sobrien { 3582130561Sobrien bfd_boolean hash; 358389857Sobrien bfd_size_type indx; 358489857Sobrien 3585130561Sobrien hash = TRUE; 358689857Sobrien if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0) 3587130561Sobrien hash = FALSE; 3588130561Sobrien indx = _bfd_stringtab_add (strtab, name, hash, FALSE); 358989857Sobrien if (indx == (bfd_size_type) -1) 3590130561Sobrien return FALSE; 359189857Sobrien sym->_n._n_n._n_zeroes = 0; 359289857Sobrien sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx; 359389857Sobrien } 3594130561Sobrien return TRUE; 359589857Sobrien} 359689857Sobrien 359789857Sobrienstatic asection * 359889857Sobrienxcoff_create_csect_from_smclas (abfd, aux, symbol_name) 359989857Sobrien bfd *abfd; 360089857Sobrien union internal_auxent *aux; 360189857Sobrien const char *symbol_name; 360289857Sobrien{ 360389857Sobrien asection *return_value = NULL; 360489857Sobrien 360589857Sobrien /* .sv64 = x_smclas == 17 360689857Sobrien This is an invalid csect for 32 bit apps. */ 360789857Sobrien static const char *names[19] = 360889857Sobrien { 360989857Sobrien ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo", 361089857Sobrien ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0", 361189857Sobrien ".td", NULL, ".sv3264" 361289857Sobrien }; 361389857Sobrien 3614104834Sobrien if ((19 >= aux->x_csect.x_smclas) 3615104834Sobrien && (NULL != names[aux->x_csect.x_smclas])) 361689857Sobrien { 361789857Sobrien return_value = bfd_make_section_anyway 361889857Sobrien (abfd, names[aux->x_csect.x_smclas]); 361989857Sobrien } 362089857Sobrien else 362189857Sobrien { 362289857Sobrien (*_bfd_error_handler) 3623218822Sdim (_("%B: symbol `%s' has unrecognized smclas %d"), 3624218822Sdim abfd, symbol_name, aux->x_csect.x_smclas); 362589857Sobrien bfd_set_error (bfd_error_bad_value); 362689857Sobrien } 362789857Sobrien 362889857Sobrien return return_value; 362989857Sobrien} 363089857Sobrien 3631130561Sobrienstatic bfd_boolean 363289857Sobrienxcoff_is_lineno_count_overflow (abfd, value) 363389857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 363489857Sobrien bfd_vma value; 363589857Sobrien{ 363689857Sobrien if (0xffff <= value) 3637130561Sobrien return TRUE; 363889857Sobrien 3639130561Sobrien return FALSE; 364089857Sobrien} 364189857Sobrien 3642130561Sobrienstatic bfd_boolean 364389857Sobrienxcoff_is_reloc_count_overflow (abfd, value) 364489857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 364589857Sobrien bfd_vma value; 364689857Sobrien{ 364789857Sobrien if (0xffff <= value) 3648130561Sobrien return TRUE; 364989857Sobrien 3650130561Sobrien return FALSE; 365189857Sobrien} 365289857Sobrien 365389857Sobrienstatic bfd_vma 365489857Sobrienxcoff_loader_symbol_offset (abfd, ldhdr) 365589857Sobrien bfd *abfd; 365689857Sobrien struct internal_ldhdr *ldhdr ATTRIBUTE_UNUSED; 365789857Sobrien{ 3658130561Sobrien return bfd_xcoff_ldhdrsz (abfd); 365989857Sobrien} 366089857Sobrien 366189857Sobrienstatic bfd_vma 366289857Sobrienxcoff_loader_reloc_offset (abfd, ldhdr) 366389857Sobrien bfd *abfd; 366489857Sobrien struct internal_ldhdr *ldhdr; 366589857Sobrien{ 3666104834Sobrien return bfd_xcoff_ldhdrsz (abfd) + ldhdr->l_nsyms * bfd_xcoff_ldsymsz (abfd); 366789857Sobrien} 366889857Sobrien 3669130561Sobrienstatic bfd_boolean 3670104834Sobrienxcoff_generate_rtinit (abfd, init, fini, rtld) 367189857Sobrien bfd *abfd; 367289857Sobrien const char *init; 367389857Sobrien const char *fini; 3674130561Sobrien bfd_boolean rtld; 367589857Sobrien{ 367689857Sobrien bfd_byte filehdr_ext[FILHSZ]; 367789857Sobrien bfd_byte scnhdr_ext[SCNHSZ]; 3678104834Sobrien bfd_byte syment_ext[SYMESZ * 10]; 3679104834Sobrien bfd_byte reloc_ext[RELSZ * 3]; 368089857Sobrien bfd_byte *data_buffer; 368189857Sobrien bfd_size_type data_buffer_size; 368291041Sobrien bfd_byte *string_table = NULL, *st_tmp = NULL; 368389857Sobrien bfd_size_type string_table_size; 368489857Sobrien bfd_vma val; 368589857Sobrien size_t initsz, finisz; 368689857Sobrien struct internal_filehdr filehdr; 368789857Sobrien struct internal_scnhdr scnhdr; 368889857Sobrien struct internal_syment syment; 368989857Sobrien union internal_auxent auxent; 369089857Sobrien struct internal_reloc reloc; 3691130561Sobrien 369289857Sobrien char *data_name = ".data"; 369389857Sobrien char *rtinit_name = "__rtinit"; 3694104834Sobrien char *rtld_name = "__rtld"; 3695130561Sobrien 3696104834Sobrien if (! bfd_xcoff_rtinit_size (abfd)) 3697130561Sobrien return FALSE; 369889857Sobrien 369989857Sobrien initsz = (init == NULL ? 0 : 1 + strlen (init)); 370089857Sobrien finisz = (fini == NULL ? 0 : 1 + strlen (fini)); 370189857Sobrien 370289857Sobrien /* file header */ 370389857Sobrien memset (filehdr_ext, 0, FILHSZ); 370489857Sobrien memset (&filehdr, 0, sizeof (struct internal_filehdr)); 370589857Sobrien filehdr.f_magic = bfd_xcoff_magic_number (abfd); 3706130561Sobrien filehdr.f_nscns = 1; 370789857Sobrien filehdr.f_timdat = 0; 3708104834Sobrien filehdr.f_nsyms = 0; /* at least 6, no more than 10 */ 370989857Sobrien filehdr.f_symptr = 0; /* set below */ 371089857Sobrien filehdr.f_opthdr = 0; 371189857Sobrien filehdr.f_flags = 0; 371289857Sobrien 371389857Sobrien /* section header */ 371489857Sobrien memset (scnhdr_ext, 0, SCNHSZ); 371589857Sobrien memset (&scnhdr, 0, sizeof (struct internal_scnhdr)); 371689857Sobrien memcpy (scnhdr.s_name, data_name, strlen (data_name)); 371789857Sobrien scnhdr.s_paddr = 0; 371889857Sobrien scnhdr.s_vaddr = 0; 371989857Sobrien scnhdr.s_size = 0; /* set below */ 372089857Sobrien scnhdr.s_scnptr = FILHSZ + SCNHSZ; 372189857Sobrien scnhdr.s_relptr = 0; /* set below */ 372289857Sobrien scnhdr.s_lnnoptr = 0; 372389857Sobrien scnhdr.s_nreloc = 0; /* either 1 or 2 */ 372489857Sobrien scnhdr.s_nlnno = 0; 372589857Sobrien scnhdr.s_flags = STYP_DATA; 372689857Sobrien 3727130561Sobrien /* .data 3728130561Sobrien 0x0000 0x00000000 : rtl 3729130561Sobrien 0x0004 0x00000010 : offset to init, or 0 3730130561Sobrien 0x0008 0x00000028 : offset to fini, or 0 3731130561Sobrien 0x000C 0x0000000C : size of descriptor 3732130561Sobrien 0x0010 0x00000000 : init, needs a reloc 3733130561Sobrien 0x0014 0x00000040 : offset to init name 3734130561Sobrien 0x0018 0x00000000 : flags, padded to a word 3735130561Sobrien 0x001C 0x00000000 : empty init 3736130561Sobrien 0x0020 0x00000000 : 3737130561Sobrien 0x0024 0x00000000 : 3738130561Sobrien 0x0028 0x00000000 : fini, needs a reloc 3739130561Sobrien 0x002C 0x00000??? : offset to fini name 3740130561Sobrien 0x0030 0x00000000 : flags, padded to a word 3741130561Sobrien 0x0034 0x00000000 : empty fini 3742130561Sobrien 0x0038 0x00000000 : 3743130561Sobrien 0x003C 0x00000000 : 3744130561Sobrien 0x0040 init name 374589857Sobrien 0x0040 + initsz fini name */ 374689857Sobrien 374789857Sobrien data_buffer_size = 0x0040 + initsz + finisz; 3748130561Sobrien data_buffer_size = (data_buffer_size + 7) &~ (bfd_size_type) 7; 374989857Sobrien data_buffer = NULL; 3750104834Sobrien data_buffer = (bfd_byte *) bfd_zmalloc (data_buffer_size); 375189857Sobrien if (data_buffer == NULL) 3752130561Sobrien return FALSE; 375389857Sobrien 3754130561Sobrien if (initsz) 375589857Sobrien { 375689857Sobrien val = 0x10; 375789857Sobrien bfd_h_put_32 (abfd, val, &data_buffer[0x04]); 375889857Sobrien val = 0x40; 375989857Sobrien bfd_h_put_32 (abfd, val, &data_buffer[0x14]); 376089857Sobrien memcpy (&data_buffer[val], init, initsz); 376189857Sobrien } 376289857Sobrien 3763130561Sobrien if (finisz) 376489857Sobrien { 376589857Sobrien val = 0x28; 376689857Sobrien bfd_h_put_32 (abfd, val, &data_buffer[0x08]); 376789857Sobrien val = 0x40 + initsz; 376889857Sobrien bfd_h_put_32 (abfd, val, &data_buffer[0x2C]); 376989857Sobrien memcpy (&data_buffer[val], fini, finisz); 377089857Sobrien } 377189857Sobrien 377289857Sobrien val = 0x0C; 377389857Sobrien bfd_h_put_32 (abfd, val, &data_buffer[0x0C]); 377489857Sobrien 377589857Sobrien scnhdr.s_size = data_buffer_size; 377689857Sobrien 377789857Sobrien /* string table */ 377889857Sobrien string_table_size = 0; 3779130561Sobrien if (initsz > 9) 378089857Sobrien string_table_size += initsz; 378189857Sobrien if (finisz > 9) 378289857Sobrien string_table_size += finisz; 378389857Sobrien if (string_table_size) 378489857Sobrien { 378589857Sobrien string_table_size += 4; 3786104834Sobrien string_table = (bfd_byte *) bfd_zmalloc (string_table_size); 3787104834Sobrien if (string_table == NULL) 3788130561Sobrien return FALSE; 3789104834Sobrien 379089857Sobrien val = string_table_size; 379189857Sobrien bfd_h_put_32 (abfd, val, &string_table[0]); 379289857Sobrien st_tmp = string_table + 4; 379389857Sobrien } 3794130561Sobrien 3795130561Sobrien /* symbols 379689857Sobrien 0. .data csect 379789857Sobrien 2. __rtinit 3798130561Sobrien 4. init function 3799130561Sobrien 6. fini function 3800104834Sobrien 8. __rtld */ 3801104834Sobrien memset (syment_ext, 0, 10 * SYMESZ); 3802104834Sobrien memset (reloc_ext, 0, 3 * RELSZ); 380389857Sobrien 380489857Sobrien /* .data csect */ 380589857Sobrien memset (&syment, 0, sizeof (struct internal_syment)); 380689857Sobrien memset (&auxent, 0, sizeof (union internal_auxent)); 380789857Sobrien memcpy (syment._n._n_name, data_name, strlen (data_name)); 380889857Sobrien syment.n_scnum = 1; 380989857Sobrien syment.n_sclass = C_HIDEXT; 381089857Sobrien syment.n_numaux = 1; 381189857Sobrien auxent.x_csect.x_scnlen.l = data_buffer_size; 381289857Sobrien auxent.x_csect.x_smtyp = 3 << 3 | XTY_SD; 381389857Sobrien auxent.x_csect.x_smclas = XMC_RW; 3814130561Sobrien bfd_coff_swap_sym_out (abfd, &syment, 381589857Sobrien &syment_ext[filehdr.f_nsyms * SYMESZ]); 3816130561Sobrien bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0, 3817130561Sobrien syment.n_numaux, 381889857Sobrien &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]); 381989857Sobrien filehdr.f_nsyms += 2; 382089857Sobrien 382189857Sobrien /* __rtinit */ 382289857Sobrien memset (&syment, 0, sizeof (struct internal_syment)); 382389857Sobrien memset (&auxent, 0, sizeof (union internal_auxent)); 382489857Sobrien memcpy (syment._n._n_name, rtinit_name, strlen (rtinit_name)); 382589857Sobrien syment.n_scnum = 1; 382689857Sobrien syment.n_sclass = C_EXT; 382789857Sobrien syment.n_numaux = 1; 382889857Sobrien auxent.x_csect.x_smtyp = XTY_LD; 382989857Sobrien auxent.x_csect.x_smclas = XMC_RW; 3830130561Sobrien bfd_coff_swap_sym_out (abfd, &syment, 383189857Sobrien &syment_ext[filehdr.f_nsyms * SYMESZ]); 3832130561Sobrien bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0, 3833130561Sobrien syment.n_numaux, 383489857Sobrien &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]); 383589857Sobrien filehdr.f_nsyms += 2; 383689857Sobrien 383789857Sobrien /* init */ 3838130561Sobrien if (initsz) 383989857Sobrien { 384089857Sobrien memset (&syment, 0, sizeof (struct internal_syment)); 384189857Sobrien memset (&auxent, 0, sizeof (union internal_auxent)); 384289857Sobrien 3843130561Sobrien if (initsz > 9) 384489857Sobrien { 384589857Sobrien syment._n._n_n._n_offset = st_tmp - string_table; 384689857Sobrien memcpy (st_tmp, init, initsz); 384789857Sobrien st_tmp += initsz; 384889857Sobrien } 384989857Sobrien else 385089857Sobrien memcpy (syment._n._n_name, init, initsz - 1); 385189857Sobrien 385289857Sobrien syment.n_sclass = C_EXT; 385389857Sobrien syment.n_numaux = 1; 3854130561Sobrien bfd_coff_swap_sym_out (abfd, &syment, 385589857Sobrien &syment_ext[filehdr.f_nsyms * SYMESZ]); 3856130561Sobrien bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0, 3857130561Sobrien syment.n_numaux, 385889857Sobrien &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]); 385989857Sobrien 386089857Sobrien /* reloc */ 386189857Sobrien memset (&reloc, 0, sizeof (struct internal_reloc)); 386289857Sobrien reloc.r_vaddr = 0x0010; 386389857Sobrien reloc.r_symndx = filehdr.f_nsyms; 386489857Sobrien reloc.r_type = R_POS; 386589857Sobrien reloc.r_size = 31; 386689857Sobrien bfd_coff_swap_reloc_out (abfd, &reloc, &reloc_ext[0]); 386789857Sobrien 386889857Sobrien filehdr.f_nsyms += 2; 386989857Sobrien scnhdr.s_nreloc += 1; 387089857Sobrien } 3871130561Sobrien 387289857Sobrien /* fini */ 3873130561Sobrien if (finisz) 387489857Sobrien { 387589857Sobrien memset (&syment, 0, sizeof (struct internal_syment)); 387689857Sobrien memset (&auxent, 0, sizeof (union internal_auxent)); 387789857Sobrien 3878130561Sobrien if (finisz > 9) 387989857Sobrien { 388089857Sobrien syment._n._n_n._n_offset = st_tmp - string_table; 388189857Sobrien memcpy (st_tmp, fini, finisz); 388289857Sobrien st_tmp += finisz; 388389857Sobrien } 388489857Sobrien else 388589857Sobrien memcpy (syment._n._n_name, fini, finisz - 1); 388689857Sobrien 388789857Sobrien syment.n_sclass = C_EXT; 388889857Sobrien syment.n_numaux = 1; 3889130561Sobrien bfd_coff_swap_sym_out (abfd, &syment, 389089857Sobrien &syment_ext[filehdr.f_nsyms * SYMESZ]); 3891130561Sobrien bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0, 3892130561Sobrien syment.n_numaux, 389389857Sobrien &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]); 389489857Sobrien 389589857Sobrien /* reloc */ 389689857Sobrien memset (&reloc, 0, sizeof (struct internal_reloc)); 389789857Sobrien reloc.r_vaddr = 0x0028; 389889857Sobrien reloc.r_symndx = filehdr.f_nsyms; 389989857Sobrien reloc.r_type = R_POS; 390089857Sobrien reloc.r_size = 31; 3901130561Sobrien bfd_coff_swap_reloc_out (abfd, &reloc, 390289857Sobrien &reloc_ext[scnhdr.s_nreloc * RELSZ]); 390389857Sobrien 390489857Sobrien filehdr.f_nsyms += 2; 390589857Sobrien scnhdr.s_nreloc += 1; 390689857Sobrien } 390789857Sobrien 3908104834Sobrien if (rtld) 3909104834Sobrien { 3910104834Sobrien memset (&syment, 0, sizeof (struct internal_syment)); 3911104834Sobrien memset (&auxent, 0, sizeof (union internal_auxent)); 3912104834Sobrien memcpy (syment._n._n_name, rtld_name, strlen (rtld_name)); 3913104834Sobrien syment.n_sclass = C_EXT; 3914104834Sobrien syment.n_numaux = 1; 3915130561Sobrien bfd_coff_swap_sym_out (abfd, &syment, 3916104834Sobrien &syment_ext[filehdr.f_nsyms * SYMESZ]); 3917130561Sobrien bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0, 3918130561Sobrien syment.n_numaux, 3919104834Sobrien &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]); 3920104834Sobrien 3921104834Sobrien /* reloc */ 3922104834Sobrien memset (&reloc, 0, sizeof (struct internal_reloc)); 3923104834Sobrien reloc.r_vaddr = 0x0000; 3924104834Sobrien reloc.r_symndx = filehdr.f_nsyms; 3925104834Sobrien reloc.r_type = R_POS; 3926104834Sobrien reloc.r_size = 31; 3927130561Sobrien bfd_coff_swap_reloc_out (abfd, &reloc, 3928104834Sobrien &reloc_ext[scnhdr.s_nreloc * RELSZ]); 3929104834Sobrien 3930104834Sobrien filehdr.f_nsyms += 2; 3931104834Sobrien scnhdr.s_nreloc += 1; 3932104834Sobrien } 3933104834Sobrien 393489857Sobrien scnhdr.s_relptr = scnhdr.s_scnptr + data_buffer_size; 393589857Sobrien filehdr.f_symptr = scnhdr.s_relptr + scnhdr.s_nreloc * RELSZ; 393689857Sobrien 393789857Sobrien bfd_coff_swap_filehdr_out (abfd, &filehdr, filehdr_ext); 393889857Sobrien bfd_bwrite (filehdr_ext, FILHSZ, abfd); 393989857Sobrien bfd_coff_swap_scnhdr_out (abfd, &scnhdr, scnhdr_ext); 394089857Sobrien bfd_bwrite (scnhdr_ext, SCNHSZ, abfd); 394189857Sobrien bfd_bwrite (data_buffer, data_buffer_size, abfd); 394289857Sobrien bfd_bwrite (reloc_ext, scnhdr.s_nreloc * RELSZ, abfd); 394389857Sobrien bfd_bwrite (syment_ext, filehdr.f_nsyms * SYMESZ, abfd); 394489857Sobrien bfd_bwrite (string_table, string_table_size, abfd); 394589857Sobrien 394689857Sobrien free (data_buffer); 394789857Sobrien data_buffer = NULL; 394889857Sobrien 3949130561Sobrien return TRUE; 395089857Sobrien} 395189857Sobrien 395289857Sobrien 395389857Sobrienstatic reloc_howto_type xcoff_dynamic_reloc = 3954130561SobrienHOWTO (0, /* type */ 3955130561Sobrien 0, /* rightshift */ 3956130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 3957130561Sobrien 32, /* bitsize */ 3958130561Sobrien FALSE, /* pc_relative */ 3959130561Sobrien 0, /* bitpos */ 396089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 3961130561Sobrien 0, /* special_function */ 3962130561Sobrien "R_POS", /* name */ 3963130561Sobrien TRUE, /* partial_inplace */ 3964130561Sobrien 0xffffffff, /* src_mask */ 3965130561Sobrien 0xffffffff, /* dst_mask */ 3966130561Sobrien FALSE); /* pcrel_offset */ 396789857Sobrien 396889857Sobrien/* glink 396989857Sobrien 397089857Sobrien The first word of global linkage code must be modified by filling in 397189857Sobrien the correct TOC offset. */ 397289857Sobrien 397389857Sobrienstatic unsigned long xcoff_glink_code[9] = 397489857Sobrien { 397589857Sobrien 0x81820000, /* lwz r12,0(r2) */ 397689857Sobrien 0x90410014, /* stw r2,20(r1) */ 397789857Sobrien 0x800c0000, /* lwz r0,0(r12) */ 397889857Sobrien 0x804c0004, /* lwz r2,4(r12) */ 397989857Sobrien 0x7c0903a6, /* mtctr r0 */ 398089857Sobrien 0x4e800420, /* bctr */ 398189857Sobrien 0x00000000, /* start of traceback table */ 398289857Sobrien 0x000c8000, /* traceback table */ 398389857Sobrien 0x00000000, /* traceback table */ 398489857Sobrien }; 398589857Sobrien 398689857Sobrien 398789857Sobrienstatic const struct xcoff_backend_data_rec bfd_xcoff_backend_data = 398889857Sobrien { 398989857Sobrien { /* COFF backend, defined in libcoff.h. */ 3990104834Sobrien _bfd_xcoff_swap_aux_in, 3991104834Sobrien _bfd_xcoff_swap_sym_in, 3992104834Sobrien coff_swap_lineno_in, 3993104834Sobrien _bfd_xcoff_swap_aux_out, 3994104834Sobrien _bfd_xcoff_swap_sym_out, 3995104834Sobrien coff_swap_lineno_out, 3996104834Sobrien xcoff_swap_reloc_out, 3997104834Sobrien coff_swap_filehdr_out, 3998104834Sobrien coff_swap_aouthdr_out, 3999104834Sobrien coff_swap_scnhdr_out, 4000104834Sobrien FILHSZ, 4001104834Sobrien AOUTSZ, 4002104834Sobrien SCNHSZ, 4003104834Sobrien SYMESZ, 4004104834Sobrien AUXESZ, 4005104834Sobrien RELSZ, 4006104834Sobrien LINESZ, 4007104834Sobrien FILNMLEN, 4008130561Sobrien TRUE, /* _bfd_coff_long_filenames */ 4009130561Sobrien FALSE, /* _bfd_coff_long_section_names */ 4010104834Sobrien 3, /* _bfd_coff_default_section_alignment_power */ 4011130561Sobrien FALSE, /* _bfd_coff_force_symnames_in_strings */ 4012130561Sobrien 2, /* _bfd_coff_debug_string_prefix_length */ 4013104834Sobrien coff_swap_filehdr_in, 4014104834Sobrien coff_swap_aouthdr_in, 4015104834Sobrien coff_swap_scnhdr_in, 4016104834Sobrien xcoff_swap_reloc_in, 4017104834Sobrien coff_bad_format_hook, 4018104834Sobrien coff_set_arch_mach_hook, 4019104834Sobrien coff_mkobject_hook, 4020104834Sobrien styp_to_sec_flags, 4021104834Sobrien coff_set_alignment_hook, 4022104834Sobrien coff_slurp_symbol_table, 4023104834Sobrien symname_in_debug_hook, 4024104834Sobrien coff_pointerize_aux_hook, 4025104834Sobrien coff_print_aux, 4026104834Sobrien dummy_reloc16_extra_cases, 4027104834Sobrien dummy_reloc16_estimate, 4028130561Sobrien NULL, /* bfd_coff_sym_is_global */ 4029104834Sobrien coff_compute_section_file_positions, 4030130561Sobrien NULL, /* _bfd_coff_start_final_link */ 4031104834Sobrien xcoff_ppc_relocate_section, 4032104834Sobrien coff_rtype_to_howto, 4033104834Sobrien NULL, /* _bfd_coff_adjust_symndx */ 4034104834Sobrien _bfd_generic_link_add_one_symbol, 4035104834Sobrien coff_link_output_has_begun, 4036104834Sobrien coff_final_link_postscript 403789857Sobrien }, 403889857Sobrien 4039130561Sobrien 0x01DF, /* magic number */ 4040104834Sobrien bfd_arch_rs6000, 4041104834Sobrien bfd_mach_rs6k, 404289857Sobrien 404389857Sobrien /* Function pointers to xcoff specific swap routines. */ 4044104834Sobrien xcoff_swap_ldhdr_in, 4045104834Sobrien xcoff_swap_ldhdr_out, 4046104834Sobrien xcoff_swap_ldsym_in, 4047104834Sobrien xcoff_swap_ldsym_out, 4048104834Sobrien xcoff_swap_ldrel_in, 4049104834Sobrien xcoff_swap_ldrel_out, 405089857Sobrien 405189857Sobrien /* Sizes. */ 4052104834Sobrien LDHDRSZ, 4053104834Sobrien LDSYMSZ, 4054104834Sobrien LDRELSZ, 4055130561Sobrien 12, /* _xcoff_function_descriptor_size */ 4056104834Sobrien SMALL_AOUTSZ, 405789857Sobrien 4058130561Sobrien /* Versions. */ 4059130561Sobrien 1, /* _xcoff_ldhdr_version */ 406089857Sobrien 4061104834Sobrien _bfd_xcoff_put_symbol_name, 4062104834Sobrien _bfd_xcoff_put_ldsymbol_name, 4063104834Sobrien &xcoff_dynamic_reloc, 4064104834Sobrien xcoff_create_csect_from_smclas, 406589857Sobrien 406689857Sobrien /* Lineno and reloc count overflow. */ 406789857Sobrien xcoff_is_lineno_count_overflow, 406889857Sobrien xcoff_is_reloc_count_overflow, 406989857Sobrien 407089857Sobrien xcoff_loader_symbol_offset, 407189857Sobrien xcoff_loader_reloc_offset, 407289857Sobrien 407389857Sobrien /* glink. */ 4074130561Sobrien &xcoff_glink_code[0], 4075104834Sobrien 36, /* _xcoff_glink_size */ 407689857Sobrien 407789857Sobrien /* rtinit */ 4078130561Sobrien 64, /* _xcoff_rtinit_size */ 4079104834Sobrien xcoff_generate_rtinit, 4080130561Sobrien }; 408189857Sobrien 4082104834Sobrien/* The transfer vector that leads the outside world to all of the above. */ 408389857Sobrienconst bfd_target rs6000coff_vec = 4084130561Sobrien { 4085130561Sobrien "aixcoff-rs6000", 4086130561Sobrien bfd_target_xcoff_flavour, 4087130561Sobrien BFD_ENDIAN_BIG, /* data byte order is big */ 4088130561Sobrien BFD_ENDIAN_BIG, /* header byte order is big */ 408989857Sobrien 4090104834Sobrien (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC 4091104834Sobrien | HAS_SYMS | HAS_LOCALS | WP_TEXT), 409289857Sobrien 4093130561Sobrien SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA, 4094130561Sobrien 0, /* leading char */ 4095130561Sobrien '/', /* ar_pad_char */ 4096104834Sobrien 15, /* ar_max_namelen */ 409789857Sobrien 4098130561Sobrien /* data */ 4099104834Sobrien bfd_getb64, 4100104834Sobrien bfd_getb_signed_64, 4101104834Sobrien bfd_putb64, 4102104834Sobrien bfd_getb32, 4103104834Sobrien bfd_getb_signed_32, 4104104834Sobrien bfd_putb32, 4105104834Sobrien bfd_getb16, 4106104834Sobrien bfd_getb_signed_16, 4107104834Sobrien bfd_putb16, 410889857Sobrien 4109130561Sobrien /* hdrs */ 4110104834Sobrien bfd_getb64, 4111104834Sobrien bfd_getb_signed_64, 4112104834Sobrien bfd_putb64, 4113104834Sobrien bfd_getb32, 4114104834Sobrien bfd_getb_signed_32, 4115104834Sobrien bfd_putb32, 4116104834Sobrien bfd_getb16, 4117104834Sobrien bfd_getb_signed_16, 4118104834Sobrien bfd_putb16, 411989857Sobrien 4120130561Sobrien { /* bfd_check_format */ 4121130561Sobrien _bfd_dummy_target, 4122130561Sobrien coff_object_p, 4123130561Sobrien _bfd_xcoff_archive_p, 4124130561Sobrien CORE_FILE_P 4125130561Sobrien }, 412689857Sobrien 4127130561Sobrien { /* bfd_set_format */ 4128130561Sobrien bfd_false, 4129130561Sobrien coff_mkobject, 4130130561Sobrien _bfd_generic_mkarchive, 4131130561Sobrien bfd_false 4132130561Sobrien }, 413389857Sobrien 4134130561Sobrien {/* bfd_write_contents */ 4135130561Sobrien bfd_false, 4136130561Sobrien coff_write_object_contents, 4137130561Sobrien _bfd_xcoff_write_archive_contents, 4138130561Sobrien bfd_false 4139130561Sobrien }, 414089857Sobrien 4141130561Sobrien /* Generic */ 4142104834Sobrien bfd_true, 4143104834Sobrien bfd_true, 4144104834Sobrien coff_new_section_hook, 4145104834Sobrien _bfd_generic_get_section_contents, 4146130561Sobrien _bfd_generic_get_section_contents_in_window, 414789857Sobrien 4148130561Sobrien /* Copy */ 4149104834Sobrien _bfd_xcoff_copy_private_bfd_data, 4150130561Sobrien ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), 4151218822Sdim _bfd_generic_init_private_section_data, 4152130561Sobrien ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true), 4153130561Sobrien ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true), 4154218822Sdim ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), 4155130561Sobrien ((bfd_boolean (*) (bfd *, flagword)) bfd_true), 4156130561Sobrien ((bfd_boolean (*) (bfd *, void * )) bfd_true), 415789857Sobrien 4158130561Sobrien /* Core */ 4159104834Sobrien coff_core_file_failing_command, 4160104834Sobrien coff_core_file_failing_signal, 4161130561Sobrien coff_core_file_matches_executable_p, 416289857Sobrien 4163130561Sobrien /* Archive */ 4164104834Sobrien _bfd_xcoff_slurp_armap, 4165104834Sobrien bfd_false, 4166130561Sobrien ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false), 4167104834Sobrien bfd_dont_truncate_arname, 4168104834Sobrien _bfd_xcoff_write_armap, 4169104834Sobrien _bfd_xcoff_read_ar_hdr, 4170104834Sobrien _bfd_xcoff_openr_next_archived_file, 4171104834Sobrien _bfd_generic_get_elt_at_index, 4172104834Sobrien _bfd_xcoff_stat_arch_elt, 4173104834Sobrien bfd_true, 417489857Sobrien 4175130561Sobrien /* Symbols */ 4176104834Sobrien coff_get_symtab_upper_bound, 4177130561Sobrien coff_canonicalize_symtab, 4178104834Sobrien coff_make_empty_symbol, 4179104834Sobrien coff_print_symbol, 4180104834Sobrien coff_get_symbol_info, 4181104834Sobrien _bfd_xcoff_is_local_label_name, 4182218822Sdim coff_bfd_is_target_special_symbol, 4183104834Sobrien coff_get_lineno, 4184104834Sobrien coff_find_nearest_line, 4185218822Sdim _bfd_generic_find_line, 4186218822Sdim coff_find_inliner_info, 4187104834Sobrien coff_bfd_make_debug_symbol, 4188104834Sobrien _bfd_generic_read_minisymbols, 4189104834Sobrien _bfd_generic_minisymbol_to_symbol, 419089857Sobrien 4191130561Sobrien /* Reloc */ 4192104834Sobrien coff_get_reloc_upper_bound, 4193104834Sobrien coff_canonicalize_reloc, 4194104834Sobrien _bfd_xcoff_reloc_type_lookup, 4195218822Sdim _bfd_xcoff_reloc_name_lookup, 419689857Sobrien 4197130561Sobrien /* Write */ 4198104834Sobrien coff_set_arch_mach, 4199104834Sobrien coff_set_section_contents, 420089857Sobrien 4201130561Sobrien /* Link */ 4202104834Sobrien _bfd_xcoff_sizeof_headers, 4203130561Sobrien bfd_generic_get_relocated_section_contents, 4204104834Sobrien bfd_generic_relax_section, 4205104834Sobrien _bfd_xcoff_bfd_link_hash_table_create, 4206104834Sobrien _bfd_generic_link_hash_table_free, 4207104834Sobrien _bfd_xcoff_bfd_link_add_symbols, 4208104834Sobrien _bfd_generic_link_just_syms, 4209104834Sobrien _bfd_xcoff_bfd_final_link, 4210104834Sobrien _bfd_generic_link_split_section, 4211104834Sobrien bfd_generic_gc_sections, 4212104834Sobrien bfd_generic_merge_sections, 4213218822Sdim bfd_generic_is_group_section, 4214104834Sobrien bfd_generic_discard_group, 4215218822Sdim _bfd_generic_section_already_linked, 421689857Sobrien 4217130561Sobrien /* Dynamic */ 4218130561Sobrien _bfd_xcoff_get_dynamic_symtab_upper_bound, 4219104834Sobrien _bfd_xcoff_canonicalize_dynamic_symtab, 4220218822Sdim _bfd_nodynamic_get_synthetic_symtab, 4221104834Sobrien _bfd_xcoff_get_dynamic_reloc_upper_bound, 4222104834Sobrien _bfd_xcoff_canonicalize_dynamic_reloc, 422389857Sobrien 4224130561Sobrien /* Opposite endian version, none exists */ 4225130561Sobrien NULL, 422689857Sobrien 4227130561Sobrien (void *) &bfd_xcoff_backend_data, 4228130561Sobrien }; 422989857Sobrien 4230104834Sobrien/* xcoff-powermac target 4231104834Sobrien Old target. 4232104834Sobrien Only difference between this target and the rs6000 target is the 4233104834Sobrien the default architecture and machine type used in coffcode.h 4234104834Sobrien 4235104834Sobrien PowerPC Macs use the same magic numbers as RS/6000 4236104834Sobrien (because that's how they were bootstrapped originally), 4237104834Sobrien but they are always PowerPC architecture. */ 423889857Sobrienstatic const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = 4239130561Sobrien { 4240104834Sobrien { /* COFF backend, defined in libcoff.h. */ 4241104834Sobrien _bfd_xcoff_swap_aux_in, 4242104834Sobrien _bfd_xcoff_swap_sym_in, 4243104834Sobrien coff_swap_lineno_in, 4244104834Sobrien _bfd_xcoff_swap_aux_out, 4245104834Sobrien _bfd_xcoff_swap_sym_out, 4246104834Sobrien coff_swap_lineno_out, 4247104834Sobrien xcoff_swap_reloc_out, 4248104834Sobrien coff_swap_filehdr_out, 4249104834Sobrien coff_swap_aouthdr_out, 4250104834Sobrien coff_swap_scnhdr_out, 4251104834Sobrien FILHSZ, 4252104834Sobrien AOUTSZ, 4253104834Sobrien SCNHSZ, 4254104834Sobrien SYMESZ, 4255104834Sobrien AUXESZ, 4256104834Sobrien RELSZ, 4257104834Sobrien LINESZ, 4258104834Sobrien FILNMLEN, 4259130561Sobrien TRUE, /* _bfd_coff_long_filenames */ 4260130561Sobrien FALSE, /* _bfd_coff_long_section_names */ 4261104834Sobrien 3, /* _bfd_coff_default_section_alignment_power */ 4262130561Sobrien FALSE, /* _bfd_coff_force_symnames_in_strings */ 4263130561Sobrien 2, /* _bfd_coff_debug_string_prefix_length */ 4264104834Sobrien coff_swap_filehdr_in, 4265104834Sobrien coff_swap_aouthdr_in, 4266104834Sobrien coff_swap_scnhdr_in, 4267104834Sobrien xcoff_swap_reloc_in, 4268104834Sobrien coff_bad_format_hook, 4269104834Sobrien coff_set_arch_mach_hook, 4270104834Sobrien coff_mkobject_hook, 4271104834Sobrien styp_to_sec_flags, 4272104834Sobrien coff_set_alignment_hook, 4273104834Sobrien coff_slurp_symbol_table, 4274104834Sobrien symname_in_debug_hook, 4275104834Sobrien coff_pointerize_aux_hook, 4276104834Sobrien coff_print_aux, 4277104834Sobrien dummy_reloc16_extra_cases, 4278104834Sobrien dummy_reloc16_estimate, 4279130561Sobrien NULL, /* bfd_coff_sym_is_global */ 4280130561Sobrien coff_compute_section_file_positions, 4281130561Sobrien NULL, /* _bfd_coff_start_final_link */ 4282104834Sobrien xcoff_ppc_relocate_section, 4283104834Sobrien coff_rtype_to_howto, 4284104834Sobrien NULL, /* _bfd_coff_adjust_symndx */ 4285104834Sobrien _bfd_generic_link_add_one_symbol, 4286104834Sobrien coff_link_output_has_begun, 4287104834Sobrien coff_final_link_postscript 4288130561Sobrien }, 428989857Sobrien 4290130561Sobrien 0x01DF, /* magic number */ 4291104834Sobrien bfd_arch_powerpc, 4292104834Sobrien bfd_mach_ppc, 429389857Sobrien 4294104834Sobrien /* Function pointers to xcoff specific swap routines. */ 4295104834Sobrien xcoff_swap_ldhdr_in, 4296104834Sobrien xcoff_swap_ldhdr_out, 4297104834Sobrien xcoff_swap_ldsym_in, 4298104834Sobrien xcoff_swap_ldsym_out, 4299104834Sobrien xcoff_swap_ldrel_in, 4300104834Sobrien xcoff_swap_ldrel_out, 430189857Sobrien 4302104834Sobrien /* Sizes. */ 4303104834Sobrien LDHDRSZ, 4304104834Sobrien LDSYMSZ, 4305104834Sobrien LDRELSZ, 4306130561Sobrien 12, /* _xcoff_function_descriptor_size */ 4307104834Sobrien SMALL_AOUTSZ, 430889857Sobrien 4309104834Sobrien /* Versions. */ 4310130561Sobrien 1, /* _xcoff_ldhdr_version */ 431189857Sobrien 4312104834Sobrien _bfd_xcoff_put_symbol_name, 4313104834Sobrien _bfd_xcoff_put_ldsymbol_name, 4314104834Sobrien &xcoff_dynamic_reloc, 4315104834Sobrien xcoff_create_csect_from_smclas, 431689857Sobrien 4317104834Sobrien /* Lineno and reloc count overflow. */ 4318130561Sobrien xcoff_is_lineno_count_overflow, 4319130561Sobrien xcoff_is_reloc_count_overflow, 432089857Sobrien 4321130561Sobrien xcoff_loader_symbol_offset, 4322130561Sobrien xcoff_loader_reloc_offset, 432389857Sobrien 4324104834Sobrien /* glink. */ 4325130561Sobrien &xcoff_glink_code[0], 4326104834Sobrien 36, /* _xcoff_glink_size */ 432789857Sobrien 4328130561Sobrien /* rtinit */ 4329130561Sobrien 0, /* _xcoff_rtinit_size */ 4330104834Sobrien xcoff_generate_rtinit, 4331130561Sobrien }; 433289857Sobrien 4333130561Sobrien/* The transfer vector that leads the outside world to all of the above. */ 433489857Sobrienconst bfd_target pmac_xcoff_vec = 4335130561Sobrien { 4336130561Sobrien "xcoff-powermac", 4337130561Sobrien bfd_target_xcoff_flavour, 4338130561Sobrien BFD_ENDIAN_BIG, /* data byte order is big */ 4339130561Sobrien BFD_ENDIAN_BIG, /* header byte order is big */ 434089857Sobrien 4341104834Sobrien (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | DYNAMIC 4342104834Sobrien | HAS_SYMS | HAS_LOCALS | WP_TEXT), 434389857Sobrien 4344130561Sobrien SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA, 4345130561Sobrien 0, /* leading char */ 4346130561Sobrien '/', /* ar_pad_char */ 4347104834Sobrien 15, /* ar_max_namelen */ 434889857Sobrien 4349130561Sobrien /* data */ 4350104834Sobrien bfd_getb64, 4351104834Sobrien bfd_getb_signed_64, 4352104834Sobrien bfd_putb64, 4353104834Sobrien bfd_getb32, 4354104834Sobrien bfd_getb_signed_32, 4355104834Sobrien bfd_putb32, 4356104834Sobrien bfd_getb16, 4357104834Sobrien bfd_getb_signed_16, 4358104834Sobrien bfd_putb16, 435989857Sobrien 4360130561Sobrien /* hdrs */ 4361104834Sobrien bfd_getb64, 4362104834Sobrien bfd_getb_signed_64, 4363104834Sobrien bfd_putb64, 4364104834Sobrien bfd_getb32, 4365104834Sobrien bfd_getb_signed_32, 4366104834Sobrien bfd_putb32, 4367104834Sobrien bfd_getb16, 4368104834Sobrien bfd_getb_signed_16, 4369104834Sobrien bfd_putb16, 437089857Sobrien 4371130561Sobrien { /* bfd_check_format */ 4372130561Sobrien _bfd_dummy_target, 4373130561Sobrien coff_object_p, 4374130561Sobrien _bfd_xcoff_archive_p, 4375130561Sobrien CORE_FILE_P 4376130561Sobrien }, 437789857Sobrien 4378130561Sobrien { /* bfd_set_format */ 4379130561Sobrien bfd_false, 4380130561Sobrien coff_mkobject, 4381130561Sobrien _bfd_generic_mkarchive, 4382130561Sobrien bfd_false 4383130561Sobrien }, 438489857Sobrien 4385130561Sobrien {/* bfd_write_contents */ 4386130561Sobrien bfd_false, 4387130561Sobrien coff_write_object_contents, 4388130561Sobrien _bfd_xcoff_write_archive_contents, 4389130561Sobrien bfd_false 4390130561Sobrien }, 439189857Sobrien 4392130561Sobrien /* Generic */ 4393104834Sobrien bfd_true, 4394104834Sobrien bfd_true, 4395104834Sobrien coff_new_section_hook, 4396104834Sobrien _bfd_generic_get_section_contents, 4397130561Sobrien _bfd_generic_get_section_contents_in_window, 439889857Sobrien 4399130561Sobrien /* Copy */ 4400104834Sobrien _bfd_xcoff_copy_private_bfd_data, 4401130561Sobrien ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), 4402218822Sdim _bfd_generic_init_private_section_data, 4403130561Sobrien ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true), 4404130561Sobrien ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true), 4405218822Sdim ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), 4406130561Sobrien ((bfd_boolean (*) (bfd *, flagword)) bfd_true), 4407130561Sobrien ((bfd_boolean (*) (bfd *, void * )) bfd_true), 440889857Sobrien 4409130561Sobrien /* Core */ 4410104834Sobrien coff_core_file_failing_command, 4411104834Sobrien coff_core_file_failing_signal, 4412130561Sobrien coff_core_file_matches_executable_p, 441389857Sobrien 4414130561Sobrien /* Archive */ 4415104834Sobrien _bfd_xcoff_slurp_armap, 4416104834Sobrien bfd_false, 4417130561Sobrien ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false), 4418104834Sobrien bfd_dont_truncate_arname, 4419104834Sobrien _bfd_xcoff_write_armap, 4420104834Sobrien _bfd_xcoff_read_ar_hdr, 4421104834Sobrien _bfd_xcoff_openr_next_archived_file, 4422104834Sobrien _bfd_generic_get_elt_at_index, 4423104834Sobrien _bfd_xcoff_stat_arch_elt, 4424104834Sobrien bfd_true, 442589857Sobrien 4426130561Sobrien /* Symbols */ 4427104834Sobrien coff_get_symtab_upper_bound, 4428130561Sobrien coff_canonicalize_symtab, 4429104834Sobrien coff_make_empty_symbol, 4430104834Sobrien coff_print_symbol, 4431104834Sobrien coff_get_symbol_info, 4432104834Sobrien _bfd_xcoff_is_local_label_name, 4433218822Sdim coff_bfd_is_target_special_symbol, 4434104834Sobrien coff_get_lineno, 4435104834Sobrien coff_find_nearest_line, 4436218822Sdim _bfd_generic_find_line, 4437218822Sdim coff_find_inliner_info, 4438104834Sobrien coff_bfd_make_debug_symbol, 4439104834Sobrien _bfd_generic_read_minisymbols, 4440104834Sobrien _bfd_generic_minisymbol_to_symbol, 444189857Sobrien 4442130561Sobrien /* Reloc */ 4443104834Sobrien coff_get_reloc_upper_bound, 4444104834Sobrien coff_canonicalize_reloc, 4445104834Sobrien _bfd_xcoff_reloc_type_lookup, 4446218822Sdim _bfd_xcoff_reloc_name_lookup, 444789857Sobrien 4448130561Sobrien /* Write */ 4449104834Sobrien coff_set_arch_mach, 4450104834Sobrien coff_set_section_contents, 445189857Sobrien 4452130561Sobrien /* Link */ 4453104834Sobrien _bfd_xcoff_sizeof_headers, 4454130561Sobrien bfd_generic_get_relocated_section_contents, 4455104834Sobrien bfd_generic_relax_section, 4456104834Sobrien _bfd_xcoff_bfd_link_hash_table_create, 4457104834Sobrien _bfd_generic_link_hash_table_free, 4458104834Sobrien _bfd_xcoff_bfd_link_add_symbols, 4459104834Sobrien _bfd_generic_link_just_syms, 4460104834Sobrien _bfd_xcoff_bfd_final_link, 4461104834Sobrien _bfd_generic_link_split_section, 4462104834Sobrien bfd_generic_gc_sections, 4463104834Sobrien bfd_generic_merge_sections, 4464218822Sdim bfd_generic_is_group_section, 4465104834Sobrien bfd_generic_discard_group, 4466218822Sdim _bfd_generic_section_already_linked, 446789857Sobrien 4468130561Sobrien /* Dynamic */ 4469130561Sobrien _bfd_xcoff_get_dynamic_symtab_upper_bound, 4470104834Sobrien _bfd_xcoff_canonicalize_dynamic_symtab, 4471218822Sdim _bfd_nodynamic_get_synthetic_symtab, 4472104834Sobrien _bfd_xcoff_get_dynamic_reloc_upper_bound, 4473104834Sobrien _bfd_xcoff_canonicalize_dynamic_reloc, 447489857Sobrien 4475130561Sobrien /* Opposite endian version, none exists */ 4476130561Sobrien NULL, 447789857Sobrien 4478130561Sobrien (void *) &bfd_pmac_xcoff_backend_data, 4479130561Sobrien }; 4480