1 /* BFD back-end for IBM RS/6000 "XCOFF64" files.
3 Free Software Foundation, Inc.
4 Written Clinton Popetz.
5 Contributed by Cygnus Support.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 /* Internalcoff.h and coffcode.h modify themselves based on these flags. */
25 #define RS6000COFF_C 1
30 #include "coff/internal.h"
31 #include "coff/rs6k64.h"
34 #define GET_FILEHDR_SYMPTR bfd_h_get_64
35 #define PUT_FILEHDR_SYMPTR bfd_h_put_64
36 #define GET_AOUTHDR_DATA_START bfd_h_get_64
37 #define PUT_AOUTHDR_DATA_START bfd_h_put_64
38 #define GET_AOUTHDR_TEXT_START bfd_h_get_64
39 #define PUT_AOUTHDR_TEXT_START bfd_h_put_64
40 #define GET_AOUTHDR_TSIZE bfd_h_get_64
41 #define PUT_AOUTHDR_TSIZE bfd_h_put_64
42 #define GET_AOUTHDR_DSIZE bfd_h_get_64
43 #define PUT_AOUTHDR_DSIZE bfd_h_put_64
44 #define GET_AOUTHDR_BSIZE bfd_h_get_64
45 #define PUT_AOUTHDR_BSIZE bfd_h_put_64
46 #define GET_AOUTHDR_ENTRY bfd_h_get_64
47 #define PUT_AOUTHDR_ENTRY bfd_h_put_64
48 #define GET_SCNHDR_PADDR bfd_h_get_64
49 #define PUT_SCNHDR_PADDR bfd_h_put_64
50 #define GET_SCNHDR_VADDR bfd_h_get_64
51 #define PUT_SCNHDR_VADDR bfd_h_put_64
52 #define GET_SCNHDR_SIZE bfd_h_get_64
53 #define PUT_SCNHDR_SIZE bfd_h_put_64
54 #define GET_SCNHDR_SCNPTR bfd_h_get_64
55 #define PUT_SCNHDR_SCNPTR bfd_h_put_64
56 #define GET_SCNHDR_RELPTR bfd_h_get_64
57 #define PUT_SCNHDR_RELPTR bfd_h_put_64
58 #define GET_SCNHDR_LNNOPTR bfd_h_get_64
59 #define PUT_SCNHDR_LNNOPTR bfd_h_put_64
60 #define GET_SCNHDR_NRELOC bfd_h_get_32
61 #define MAX_SCNHDR_NRELOC 0xffffffff
62 #define PUT_SCNHDR_NRELOC bfd_h_put_32
63 #define GET_SCNHDR_NLNNO bfd_h_get_32
64 #define MAX_SCNHDR_NLNNO 0xffffffff
65 #define PUT_SCNHDR_NLNNO bfd_h_put_32
66 #define GET_RELOC_VADDR bfd_h_get_64
67 #define PUT_RELOC_VADDR bfd_h_put_64
69 #define COFF_FORCE_SYMBOLS_IN_STRINGS
70 #define COFF_DEBUG_STRING_WIDE_PREFIX
72 #define COFF_ADJUST_SCNHDR_OUT_POST(ABFD,INT,EXT) \
74 memset (((SCNHDR *)EXT)->s_pad, 0, sizeof (((SCNHDR *)EXT)->s_pad));\
77 #define NO_COFF_LINENOS
79 #define coff_SWAP_lineno_in xcoff64_swap_lineno_in
80 #define coff_SWAP_lineno_out xcoff64_swap_lineno_out
82 #define PUTWORD bfd_h_put_32
83 #define PUTHALF bfd_h_put_16
84 #define PUTBYTE bfd_h_put_8
85 #define GETWORD bfd_h_get_32
86 #define GETHALF bfd_h_get_16
87 #define GETBYTE bfd_h_get_8
89 /* For XCOFF64, the effective width of symndx changes depending on
90 whether we are the first entry. Sigh. */
92 xcoff64_swap_lineno_in (abfd
, ext1
, in1
)
97 LINENO
*ext
= (LINENO
*)ext1
;
98 struct internal_lineno
*in
= (struct internal_lineno
*)in1
;
100 in
->l_lnno
= bfd_h_get_32(abfd
, (bfd_byte
*) (ext
->l_lnno
));
102 in
->l_addr
.l_symndx
=
103 bfd_h_get_32(abfd
, (bfd_byte
*) ext
->l_addr
.l_symndx
);
105 in
->l_addr
.l_symndx
=
106 bfd_h_get_64(abfd
, (bfd_byte
*) ext
->l_addr
.l_symndx
);
110 xcoff64_swap_lineno_out (abfd
, inp
, outp
)
115 struct internal_lineno
*in
= (struct internal_lineno
*)inp
;
116 struct external_lineno
*ext
= (struct external_lineno
*)outp
;
117 PUTWORD(abfd
, in
->l_addr
.l_symndx
, (bfd_byte
*)
118 ext
->l_addr
.l_symndx
);
120 bfd_h_put_32 (abfd
, in
->l_lnno
, (bfd_byte
*) (ext
->l_lnno
));
122 bfd_h_put_32 (abfd
, in
->l_addr
.l_symndx
, (bfd_byte
*)ext
->l_addr
.l_symndx
);
124 bfd_h_put_64 (abfd
, in
->l_addr
.l_symndx
, (bfd_byte
*)ext
->l_addr
.l_symndx
);
126 return bfd_coff_linesz (abfd
);
129 static void xcoff64_swap_sym_in
PARAMS ((bfd
*, PTR
, PTR
));
130 static unsigned int xcoff64_swap_sym_out
PARAMS ((bfd
*, PTR
, PTR
));
131 static void xcoff64_swap_aux_in
PARAMS ((bfd
*, PTR
, int, int, int, int, PTR
));
132 static unsigned int xcoff64_swap_aux_out
PARAMS ((bfd
*, PTR
, int, int, int, int, PTR
));
135 xcoff64_swap_sym_in (abfd
, ext1
, in1
)
140 SYMENT
*ext
= (SYMENT
*)ext1
;
141 struct internal_syment
*in
= (struct internal_syment
*)in1
;
143 in
->_n
._n_n
._n_zeroes
= 0;
144 in
->_n
._n_n
._n_offset
= bfd_h_get_32(abfd
, (bfd_byte
*) ext
->e_offset
);
145 in
->n_value
= bfd_h_get_64(abfd
, (bfd_byte
*) ext
->e
.e_value
);
146 in
->n_scnum
= bfd_h_get_16(abfd
, (bfd_byte
*) ext
->e_scnum
);
147 in
->n_type
= bfd_h_get_16(abfd
, (bfd_byte
*) ext
->e_type
);
148 in
->n_sclass
= bfd_h_get_8(abfd
, ext
->e_sclass
);
149 in
->n_numaux
= bfd_h_get_8(abfd
, ext
->e_numaux
);
153 xcoff64_swap_sym_out (abfd
, inp
, extp
)
158 struct internal_syment
*in
= (struct internal_syment
*)inp
;
159 SYMENT
*ext
=(SYMENT
*)extp
;
161 bfd_h_put_32(abfd
, in
->_n
._n_n
._n_offset
, (bfd_byte
*) ext
->e_offset
);
162 bfd_h_put_64(abfd
, in
->n_value
, (bfd_byte
*) ext
->e
.e_value
);
163 bfd_h_put_16(abfd
, in
->n_scnum
, (bfd_byte
*) ext
->e_scnum
);
164 bfd_h_put_16(abfd
, in
->n_type
, (bfd_byte
*) ext
->e_type
);
165 bfd_h_put_8(abfd
, in
->n_sclass
, ext
->e_sclass
);
166 bfd_h_put_8(abfd
, in
->n_numaux
, ext
->e_numaux
);
167 return bfd_coff_symesz (abfd
);
171 xcoff64_swap_aux_in (abfd
, ext1
, type
, class, indx
, numaux
, in1
)
180 AUXENT
*ext
= (AUXENT
*)ext1
;
181 union internal_auxent
*in
= (union internal_auxent
*)in1
;
185 if (ext
->x_file
.x_fname
[0] == 0) {
186 in
->x_file
.x_n
.x_zeroes
= 0;
187 in
->x_file
.x_n
.x_offset
=
188 bfd_h_get_32(abfd
, (bfd_byte
*) ext
->x_file
.x_n
.x_offset
);
193 memcpy (in
->x_file
.x_fname
, ext
->x_file
.x_fname
,
194 numaux
* sizeof (AUXENT
));
198 memcpy (in
->x_file
.x_fname
, ext
->x_file
.x_fname
, FILNMLEN
);
203 /* RS/6000 "csect" auxents */
206 if (indx
+ 1 == numaux
)
208 in
->x_csect
.x_scnlen
.l
=
209 bfd_h_get_32(abfd
, ext
->x_csect
.x_scnlen_lo
);
210 /* FIXME: If we want section lengths larger than 32 bits, we need
211 to modify the internal coff structures to support it. */
212 in
->x_csect
.x_parmhash
= bfd_h_get_32 (abfd
,
213 ext
->x_csect
.x_parmhash
);
214 in
->x_csect
.x_snhash
= bfd_h_get_16 (abfd
, ext
->x_csect
.x_snhash
);
215 /* We don't have to hack bitfields in x_smtyp because it's
216 defined by shifts-and-ands, which are equivalent on all
218 in
->x_csect
.x_smtyp
= bfd_h_get_8 (abfd
, ext
->x_csect
.x_smtyp
);
219 in
->x_csect
.x_smclas
= bfd_h_get_8 (abfd
, ext
->x_csect
.x_smclas
);
227 if (type
== T_NULL
) {
228 /* PE defines some extra fields; we zero them out for
230 in
->x_scn
.x_checksum
= 0;
231 in
->x_scn
.x_associated
= 0;
232 in
->x_scn
.x_comdat
= 0;
239 if (class == C_BLOCK
|| class == C_FCN
|| ISFCN (type
) || ISTAG (class))
241 in
->x_sym
.x_fcnary
.x_fcn
.x_lnnoptr
= bfd_h_get_64(abfd
, (bfd_byte
*)
242 ext
->x_sym
.x_fcnary
.x_fcn
.x_lnnoptr
);
243 in
->x_sym
.x_fcnary
.x_fcn
.x_endndx
.l
= bfd_h_get_32(abfd
, (bfd_byte
*)
244 ext
->x_sym
.x_fcnary
.x_fcn
.x_endndx
);
247 in
->x_sym
.x_misc
.x_fsize
= bfd_h_get_32(abfd
, (bfd_byte
*) ext
->x_sym
.x_fcnary
.x_fcn
.x_fsize
);
250 in
->x_sym
.x_misc
.x_lnsz
.x_lnno
= bfd_h_get_32(abfd
, (bfd_byte
*)
251 ext
->x_sym
.x_fcnary
.x_lnsz
.x_lnno
);
252 in
->x_sym
.x_misc
.x_lnsz
.x_size
= bfd_h_get_16(abfd
, (bfd_byte
*)
253 ext
->x_sym
.x_fcnary
.x_lnsz
.x_size
);
257 /* the semicolon is because MSVC doesn't like labels at
263 xcoff64_swap_aux_out (abfd
, inp
, type
, class, indx
, numaux
, extp
)
268 int indx ATTRIBUTE_UNUSED
;
269 int numaux ATTRIBUTE_UNUSED
;
272 union internal_auxent
*in
= (union internal_auxent
*)inp
;
273 AUXENT
*ext
= (AUXENT
*)extp
;
275 memset((PTR
)ext
, 0, bfd_coff_auxesz (abfd
));
279 if (in
->x_file
.x_fname
[0] == 0)
281 PUTWORD(abfd
, 0, (bfd_byte
*) ext
->x_file
.x_n
.x_zeroes
);
283 in
->x_file
.x_n
.x_offset
,
284 (bfd_byte
*) ext
->x_file
.x_n
.x_offset
);
288 memcpy (ext
->x_file
.x_fname
, in
->x_file
.x_fname
, FILNMLEN
);
290 PUTBYTE (abfd
, _AUX_FILE
, (bfd_byte
*) ext
->x_auxtype
.x_auxtype
);
293 /* RS/6000 "csect" auxents */
296 if (indx
+ 1 == numaux
)
298 PUTWORD (abfd
, in
->x_csect
.x_scnlen
.l
, ext
->x_csect
.x_scnlen_lo
);
299 PUTWORD (abfd
, in
->x_csect
.x_parmhash
, ext
->x_csect
.x_parmhash
);
300 PUTHALF (abfd
, in
->x_csect
.x_snhash
, ext
->x_csect
.x_snhash
);
301 /* We don't have to hack bitfields in x_smtyp because it's
302 defined by shifts-and-ands, which are equivalent on all
304 PUTBYTE (abfd
, in
->x_csect
.x_smtyp
, ext
->x_csect
.x_smtyp
);
305 PUTBYTE (abfd
, in
->x_csect
.x_smclas
, ext
->x_csect
.x_smclas
);
306 PUTBYTE (abfd
, _AUX_CSECT
, (bfd_byte
*) ext
->x_auxtype
.x_auxtype
);
314 if (type
== T_NULL
) {
320 if (class == C_BLOCK
|| class == C_FCN
|| ISFCN (type
) || ISTAG (class))
322 bfd_h_put_64(abfd
, in
->x_sym
.x_fcnary
.x_fcn
.x_lnnoptr
,
323 (bfd_byte
*) ext
->x_sym
.x_fcnary
.x_fcn
.x_lnnoptr
);
324 PUTBYTE (abfd
, _AUX_FCN
, (bfd_byte
*) ext
->x_auxtype
.x_auxtype
);
325 PUTWORD(abfd
, in
->x_sym
.x_fcnary
.x_fcn
.x_endndx
.l
,
326 (bfd_byte
*) ext
->x_sym
.x_fcnary
.x_fcn
.x_endndx
);
329 PUTWORD (abfd
, in
->x_sym
.x_misc
.x_fsize
,
330 (bfd_byte
*) ext
->x_sym
.x_fcnary
.x_fcn
.x_fsize
);
333 bfd_h_put_32(abfd
, in
->x_sym
.x_misc
.x_lnsz
.x_lnno
,
334 (bfd_byte
*)ext
->x_sym
.x_fcnary
.x_lnsz
.x_lnno
);
335 bfd_h_put_16(abfd
, in
->x_sym
.x_misc
.x_lnsz
.x_size
,
336 (bfd_byte
*)ext
->x_sym
.x_fcnary
.x_lnsz
.x_size
);
340 return bfd_coff_auxesz (abfd
);
343 #define coff_SWAP_sym_in xcoff64_swap_sym_in
344 #define coff_SWAP_sym_out xcoff64_swap_sym_out
345 #define coff_SWAP_aux_in xcoff64_swap_aux_in
346 #define coff_SWAP_aux_out xcoff64_swap_aux_out
348 #define TARGET_NAME "aixcoff64-rs6000"
349 #define TARGET_SYM rs6000coff64_vec
351 #include "xcoff-target.h"