1 /* Generic COFF swapping routines, for BFD.
2    Copyright (C) 1990-2021 Free Software Foundation, Inc.
3    Written by Cygnus Support.
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 /* This file contains routines used to swap COFF data.  It is a header
23    file because the details of swapping depend on the details of the
24    structures used by each COFF implementation.  This is included by
25    coffcode.h, as well as by the ECOFF backend.
26 
27    Any file which uses this must first include "coff/internal.h" and
28    "coff/CPU.h".  The functions will then be correct for that CPU.  */
29 
30 #ifndef GET_FCN_LNNOPTR
31 #define GET_FCN_LNNOPTR(abfd, ext) \
32   H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
33 #endif
34 
35 #ifndef GET_FCN_ENDNDX
36 #define GET_FCN_ENDNDX(abfd, ext) \
37   H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx)
38 #endif
39 
40 #ifndef PUT_FCN_LNNOPTR
41 #define PUT_FCN_LNNOPTR(abfd, in, ext) \
42   H_PUT_32 (abfd,  in, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
43 #endif
44 #ifndef PUT_FCN_ENDNDX
45 #define PUT_FCN_ENDNDX(abfd, in, ext) \
46   H_PUT_32 (abfd, in, ext->x_sym.x_fcnary.x_fcn.x_endndx)
47 #endif
48 #ifndef GET_LNSZ_LNNO
49 #define GET_LNSZ_LNNO(abfd, ext) \
50   H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_lnno)
51 #endif
52 #ifndef GET_LNSZ_SIZE
53 #define GET_LNSZ_SIZE(abfd, ext) \
54   H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size)
55 #endif
56 #ifndef PUT_LNSZ_LNNO
57 #define PUT_LNSZ_LNNO(abfd, in, ext) \
58   H_PUT_16 (abfd, in, ext->x_sym.x_misc.x_lnsz.x_lnno)
59 #endif
60 #ifndef PUT_LNSZ_SIZE
61 #define PUT_LNSZ_SIZE(abfd, in, ext) \
62   H_PUT_16 (abfd, in, ext->x_sym.x_misc.x_lnsz.x_size)
63 #endif
64 #ifndef GET_SCN_SCNLEN
65 #define GET_SCN_SCNLEN(abfd, ext) \
66   H_GET_32 (abfd, ext->x_scn.x_scnlen)
67 #endif
68 #ifndef GET_SCN_NRELOC
69 #define GET_SCN_NRELOC(abfd, ext) \
70   H_GET_16 (abfd, ext->x_scn.x_nreloc)
71 #endif
72 #ifndef GET_SCN_NLINNO
73 #define GET_SCN_NLINNO(abfd, ext) \
74   H_GET_16 (abfd, ext->x_scn.x_nlinno)
75 #endif
76 #ifndef PUT_SCN_SCNLEN
77 #define PUT_SCN_SCNLEN(abfd, in, ext) \
78   H_PUT_32 (abfd, in, ext->x_scn.x_scnlen)
79 #endif
80 #ifndef PUT_SCN_NRELOC
81 #define PUT_SCN_NRELOC(abfd, in, ext) \
82   H_PUT_16 (abfd, in, ext->x_scn.x_nreloc)
83 #endif
84 #ifndef PUT_SCN_NLINNO
85 #define PUT_SCN_NLINNO(abfd, in, ext) \
86   H_PUT_16 (abfd, in, ext->x_scn.x_nlinno)
87 #endif
88 #ifndef GET_LINENO_LNNO
89 #define GET_LINENO_LNNO(abfd, ext) \
90   H_GET_16 (abfd, ext->l_lnno);
91 #endif
92 #ifndef PUT_LINENO_LNNO
93 #define PUT_LINENO_LNNO(abfd, val, ext) \
94   H_PUT_16 (abfd, val, ext->l_lnno);
95 #endif
96 
97 /* The f_symptr field in the filehdr is sometimes 64 bits.  */
98 #ifndef GET_FILEHDR_SYMPTR
99 #define GET_FILEHDR_SYMPTR H_GET_32
100 #endif
101 #ifndef PUT_FILEHDR_SYMPTR
102 #define PUT_FILEHDR_SYMPTR H_PUT_32
103 #endif
104 
105 /* Some fields in the aouthdr are sometimes 64 bits.  */
106 #ifndef GET_AOUTHDR_TSIZE
107 #define GET_AOUTHDR_TSIZE H_GET_32
108 #endif
109 #ifndef PUT_AOUTHDR_TSIZE
110 #define PUT_AOUTHDR_TSIZE H_PUT_32
111 #endif
112 #ifndef GET_AOUTHDR_DSIZE
113 #define GET_AOUTHDR_DSIZE H_GET_32
114 #endif
115 #ifndef PUT_AOUTHDR_DSIZE
116 #define PUT_AOUTHDR_DSIZE H_PUT_32
117 #endif
118 #ifndef GET_AOUTHDR_BSIZE
119 #define GET_AOUTHDR_BSIZE H_GET_32
120 #endif
121 #ifndef PUT_AOUTHDR_BSIZE
122 #define PUT_AOUTHDR_BSIZE H_PUT_32
123 #endif
124 #ifndef GET_AOUTHDR_ENTRY
125 #define GET_AOUTHDR_ENTRY H_GET_32
126 #endif
127 #ifndef PUT_AOUTHDR_ENTRY
128 #define PUT_AOUTHDR_ENTRY H_PUT_32
129 #endif
130 #ifndef GET_AOUTHDR_TEXT_START
131 #define GET_AOUTHDR_TEXT_START H_GET_32
132 #endif
133 #ifndef PUT_AOUTHDR_TEXT_START
134 #define PUT_AOUTHDR_TEXT_START H_PUT_32
135 #endif
136 #ifndef GET_AOUTHDR_DATA_START
137 #define GET_AOUTHDR_DATA_START H_GET_32
138 #endif
139 #ifndef PUT_AOUTHDR_DATA_START
140 #define PUT_AOUTHDR_DATA_START H_PUT_32
141 #endif
142 
143 /* Some fields in the scnhdr are sometimes 64 bits.  */
144 #ifndef GET_SCNHDR_PADDR
145 #define GET_SCNHDR_PADDR H_GET_32
146 #endif
147 #ifndef PUT_SCNHDR_PADDR
148 #define PUT_SCNHDR_PADDR H_PUT_32
149 #endif
150 #ifndef GET_SCNHDR_VADDR
151 #define GET_SCNHDR_VADDR H_GET_32
152 #endif
153 #ifndef PUT_SCNHDR_VADDR
154 #define PUT_SCNHDR_VADDR H_PUT_32
155 #endif
156 #ifndef GET_SCNHDR_SIZE
157 #define GET_SCNHDR_SIZE H_GET_32
158 #endif
159 #ifndef PUT_SCNHDR_SIZE
160 #define PUT_SCNHDR_SIZE H_PUT_32
161 #endif
162 #ifndef GET_SCNHDR_SCNPTR
163 #define GET_SCNHDR_SCNPTR H_GET_32
164 #endif
165 #ifndef PUT_SCNHDR_SCNPTR
166 #define PUT_SCNHDR_SCNPTR H_PUT_32
167 #endif
168 #ifndef GET_SCNHDR_RELPTR
169 #define GET_SCNHDR_RELPTR H_GET_32
170 #endif
171 #ifndef PUT_SCNHDR_RELPTR
172 #define PUT_SCNHDR_RELPTR H_PUT_32
173 #endif
174 #ifndef GET_SCNHDR_LNNOPTR
175 #define GET_SCNHDR_LNNOPTR H_GET_32
176 #endif
177 #ifndef PUT_SCNHDR_LNNOPTR
178 #define PUT_SCNHDR_LNNOPTR H_PUT_32
179 #endif
180 #ifndef GET_SCNHDR_NRELOC
181 #define GET_SCNHDR_NRELOC H_GET_16
182 #endif
183 #ifndef MAX_SCNHDR_NRELOC
184 #define MAX_SCNHDR_NRELOC 0xffff
185 #endif
186 #ifndef PUT_SCNHDR_NRELOC
187 #define PUT_SCNHDR_NRELOC H_PUT_16
188 #endif
189 #ifndef GET_SCNHDR_NLNNO
190 #define GET_SCNHDR_NLNNO H_GET_16
191 #endif
192 #ifndef MAX_SCNHDR_NLNNO
193 #define MAX_SCNHDR_NLNNO 0xffff
194 #endif
195 #ifndef PUT_SCNHDR_NLNNO
196 #define PUT_SCNHDR_NLNNO H_PUT_16
197 #endif
198 #ifndef GET_SCNHDR_FLAGS
199 #define GET_SCNHDR_FLAGS H_GET_32
200 #endif
201 #ifndef PUT_SCNHDR_FLAGS
202 #define PUT_SCNHDR_FLAGS H_PUT_32
203 #endif
204 
205 #ifndef GET_RELOC_VADDR
206 #define GET_RELOC_VADDR H_GET_32
207 #endif
208 #ifndef PUT_RELOC_VADDR
209 #define PUT_RELOC_VADDR H_PUT_32
210 #endif
211 
212 #ifndef NO_COFF_RELOCS
213 
214 static void
coff_swap_reloc_in(bfd * abfd,void * src,void * dst)215 coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
216 {
217   RELOC *reloc_src = (RELOC *) src;
218   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
219 
220   reloc_dst->r_vaddr  = GET_RELOC_VADDR (abfd, reloc_src->r_vaddr);
221   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
222   reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
223 
224 #ifdef SWAP_IN_RELOC_OFFSET
225   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset);
226 #endif
227 }
228 
229 static unsigned int
coff_swap_reloc_out(bfd * abfd,void * src,void * dst)230 coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
231 {
232   struct internal_reloc *reloc_src = (struct internal_reloc *) src;
233   struct external_reloc *reloc_dst = (struct external_reloc *) dst;
234 
235   PUT_RELOC_VADDR (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
236   H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
237   H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
238 
239 #ifdef SWAP_OUT_RELOC_OFFSET
240   SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset);
241 #endif
242 #ifdef SWAP_OUT_RELOC_EXTRA
243   SWAP_OUT_RELOC_EXTRA (abfd, reloc_src, reloc_dst);
244 #endif
245 
246   return bfd_coff_relsz (abfd);
247 }
248 
249 #endif /* NO_COFF_RELOCS */
250 
251 static void
coff_swap_filehdr_in(bfd * abfd,void * src,void * dst)252 coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
253 {
254   FILHDR *filehdr_src = (FILHDR *) src;
255   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
256 
257 #ifdef COFF_ADJUST_FILEHDR_IN_PRE
258   COFF_ADJUST_FILEHDR_IN_PRE (abfd, src, dst);
259 #endif
260   filehdr_dst->f_magic  = H_GET_16 (abfd, filehdr_src->f_magic);
261   filehdr_dst->f_nscns  = H_GET_16 (abfd, filehdr_src->f_nscns);
262   filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->f_timdat);
263   filehdr_dst->f_symptr = GET_FILEHDR_SYMPTR (abfd, filehdr_src->f_symptr);
264   filehdr_dst->f_nsyms  = H_GET_32 (abfd, filehdr_src->f_nsyms);
265   filehdr_dst->f_opthdr = H_GET_16 (abfd, filehdr_src->f_opthdr);
266   filehdr_dst->f_flags  = H_GET_16 (abfd, filehdr_src->f_flags);
267 
268 #ifdef COFF_ADJUST_FILEHDR_IN_POST
269   COFF_ADJUST_FILEHDR_IN_POST (abfd, src, dst);
270 #endif
271 }
272 
273 static  unsigned int
coff_swap_filehdr_out(bfd * abfd,void * in,void * out)274 coff_swap_filehdr_out (bfd *abfd, void * in, void * out)
275 {
276   struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
277   FILHDR *filehdr_out = (FILHDR *) out;
278 
279 #ifdef COFF_ADJUST_FILEHDR_OUT_PRE
280   COFF_ADJUST_FILEHDR_OUT_PRE (abfd, in, out);
281 #endif
282   H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
283   H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns);
284   H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->f_timdat);
285   PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr);
286   H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms);
287   H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr);
288   H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags);
289 
290 #ifdef COFF_ADJUST_FILEHDR_OUT_POST
291   COFF_ADJUST_FILEHDR_OUT_POST (abfd, in, out);
292 #endif
293   return bfd_coff_filhsz (abfd);
294 }
295 
296 #ifndef NO_COFF_SYMBOLS
297 
298 static void
coff_swap_sym_in(bfd * abfd,void * ext1,void * in1)299 coff_swap_sym_in (bfd * abfd, void * ext1, void * in1)
300 {
301   SYMENT *ext = (SYMENT *) ext1;
302   struct internal_syment *in = (struct internal_syment *) in1;
303 
304   if (ext->e.e_name[0] == 0)
305     {
306       in->_n._n_n._n_zeroes = 0;
307       in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset);
308     }
309   else
310     {
311 #if SYMNMLEN != E_SYMNMLEN
312 #error we need to cope with truncating or extending SYMNMLEN
313 #else
314       memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN);
315 #endif
316     }
317 
318   in->n_value = H_GET_32 (abfd, ext->e_value);
319   in->n_scnum = (short) H_GET_16 (abfd, ext->e_scnum);
320   if (sizeof (ext->e_type) == 2)
321     in->n_type = H_GET_16 (abfd, ext->e_type);
322   else
323     in->n_type = H_GET_32 (abfd, ext->e_type);
324   in->n_sclass = H_GET_8 (abfd, ext->e_sclass);
325   in->n_numaux = H_GET_8 (abfd, ext->e_numaux);
326 #ifdef COFF_ADJUST_SYM_IN_POST
327   COFF_ADJUST_SYM_IN_POST (abfd, ext1, in1);
328 #endif
329 }
330 
331 static unsigned int
coff_swap_sym_out(bfd * abfd,void * inp,void * extp)332 coff_swap_sym_out (bfd * abfd, void * inp, void * extp)
333 {
334   struct internal_syment *in = (struct internal_syment *) inp;
335   SYMENT *ext =(SYMENT *) extp;
336 
337 #ifdef COFF_ADJUST_SYM_OUT_PRE
338   COFF_ADJUST_SYM_OUT_PRE (abfd, inp, extp);
339 #endif
340 
341   if (in->_n._n_name[0] == 0)
342     {
343       H_PUT_32 (abfd, 0, ext->e.e.e_zeroes);
344       H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset);
345     }
346   else
347     {
348 #if SYMNMLEN != E_SYMNMLEN
349 #error we need to cope with truncating or extending SYMNMLEN
350 #else
351       memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN);
352 #endif
353     }
354 
355   H_PUT_32 (abfd, in->n_value, ext->e_value);
356   H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);
357 
358   if (sizeof (ext->e_type) == 2)
359     H_PUT_16 (abfd, in->n_type, ext->e_type);
360   else
361     H_PUT_32 (abfd, in->n_type, ext->e_type);
362 
363   H_PUT_8 (abfd, in->n_sclass, ext->e_sclass);
364   H_PUT_8 (abfd, in->n_numaux, ext->e_numaux);
365 
366 #ifdef COFF_ADJUST_SYM_OUT_POST
367   COFF_ADJUST_SYM_OUT_POST (abfd, inp, extp);
368 #endif
369 
370   return SYMESZ;
371 }
372 
373 static void
coff_swap_aux_in(bfd * abfd,void * ext1,int type,int in_class,int indx,int numaux,void * in1)374 coff_swap_aux_in (bfd *abfd,
375 		  void * ext1,
376 		  int type,
377 		  int in_class,
378 		  int indx,
379 		  int numaux,
380 		  void * in1)
381 {
382   AUXENT *ext = (AUXENT *) ext1;
383   union internal_auxent *in = (union internal_auxent *) in1;
384 
385 #ifdef COFF_ADJUST_AUX_IN_PRE
386   COFF_ADJUST_AUX_IN_PRE (abfd, ext1, type, in_class, indx, numaux, in1);
387 #endif
388 
389   switch (in_class)
390     {
391     case C_FILE:
392       if (ext->x_file.x_fname[0] == 0)
393 	{
394 	  in->x_file.x_n.x_zeroes = 0;
395 	  in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
396 	}
397       else
398 	{
399 #if FILNMLEN != E_FILNMLEN
400 #error we need to cope with truncating or extending FILNMLEN
401 #else
402 	  if (numaux > 1 && coff_data (abfd)->pe)
403 	    {
404 	      if (indx == 0)
405 		memcpy (in->x_file.x_fname, ext->x_file.x_fname,
406 			numaux * sizeof (AUXENT));
407 	    }
408 	  else
409 	    memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
410 #endif
411 	}
412       goto end;
413 
414     case C_STAT:
415 #ifdef C_LEAFSTAT
416     case C_LEAFSTAT:
417 #endif
418     case C_HIDDEN:
419       if (type == T_NULL)
420 	{
421 	  in->x_scn.x_scnlen = GET_SCN_SCNLEN (abfd, ext);
422 	  in->x_scn.x_nreloc = GET_SCN_NRELOC (abfd, ext);
423 	  in->x_scn.x_nlinno = GET_SCN_NLINNO (abfd, ext);
424 
425 	  /* PE defines some extra fields; we zero them out for
426 	     safety.  */
427 	  in->x_scn.x_checksum = 0;
428 	  in->x_scn.x_associated = 0;
429 	  in->x_scn.x_comdat = 0;
430 
431 	  goto end;
432 	}
433       break;
434     }
435 
436   in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
437 #ifndef NO_TVNDX
438   in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
439 #endif
440 
441   if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
442       || ISTAG (in_class))
443     {
444       in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
445       in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
446     }
447   else
448     {
449 #if DIMNUM != E_DIMNUM
450 #error we need to cope with truncating or extending DIMNUM
451 #endif
452       in->x_sym.x_fcnary.x_ary.x_dimen[0] =
453 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
454       in->x_sym.x_fcnary.x_ary.x_dimen[1] =
455 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
456       in->x_sym.x_fcnary.x_ary.x_dimen[2] =
457 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
458       in->x_sym.x_fcnary.x_ary.x_dimen[3] =
459 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
460     }
461 
462   if (ISFCN (type))
463     in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize);
464   else
465     {
466       in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO (abfd, ext);
467       in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE (abfd, ext);
468     }
469 
470  end: ;
471 
472 #ifdef COFF_ADJUST_AUX_IN_POST
473   COFF_ADJUST_AUX_IN_POST (abfd, ext1, type, in_class, indx, numaux, in1);
474 #endif
475 }
476 
477 static unsigned int
coff_swap_aux_out(bfd * abfd,void * inp,int type,int in_class,int indx ATTRIBUTE_UNUSED,int numaux ATTRIBUTE_UNUSED,void * extp)478 coff_swap_aux_out (bfd * abfd,
479 		   void * inp,
480 		   int type,
481 		   int in_class,
482 		   int indx ATTRIBUTE_UNUSED,
483 		   int numaux ATTRIBUTE_UNUSED,
484 		   void * extp)
485 {
486   union internal_auxent * in = (union internal_auxent *) inp;
487   AUXENT *ext = (AUXENT *) extp;
488 
489 #ifdef COFF_ADJUST_AUX_OUT_PRE
490   COFF_ADJUST_AUX_OUT_PRE (abfd, inp, type, in_class, indx, numaux, extp);
491 #endif
492 
493   memset (ext, 0, AUXESZ);
494 
495   switch (in_class)
496     {
497     case C_FILE:
498       if (in->x_file.x_fname[0] == 0)
499 	{
500 	  H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
501 	  H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
502 	}
503       else
504 	{
505 #if FILNMLEN != E_FILNMLEN
506 #error we need to cope with truncating or extending FILNMLEN
507 #else
508 	  memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
509 #endif
510 	}
511       goto end;
512 
513     case C_STAT:
514 #ifdef C_LEAFSTAT
515     case C_LEAFSTAT:
516 #endif
517     case C_HIDDEN:
518       if (type == T_NULL)
519 	{
520 	  PUT_SCN_SCNLEN (abfd, in->x_scn.x_scnlen, ext);
521 	  PUT_SCN_NRELOC (abfd, in->x_scn.x_nreloc, ext);
522 	  PUT_SCN_NLINNO (abfd, in->x_scn.x_nlinno, ext);
523 	  goto end;
524 	}
525       break;
526     }
527 
528   H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
529 #ifndef NO_TVNDX
530   H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
531 #endif
532 
533   if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
534       || ISTAG (in_class))
535     {
536       PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
537       PUT_FCN_ENDNDX (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
538     }
539   else
540     {
541 #if DIMNUM != E_DIMNUM
542 #error we need to cope with truncating or extending DIMNUM
543 #endif
544       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
545 	       ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
546       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
547 	       ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
548       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
549 	       ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
550       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
551 	       ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
552     }
553 
554   if (ISFCN (type))
555     H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize);
556   else
557     {
558       PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
559       PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
560     }
561 
562  end:
563 #ifdef COFF_ADJUST_AUX_OUT_POST
564   COFF_ADJUST_AUX_OUT_POST (abfd, inp, type, in_class, indx, numaux, extp);
565 #endif
566   return AUXESZ;
567 }
568 
569 #endif /* NO_COFF_SYMBOLS */
570 
571 #ifndef NO_COFF_LINENOS
572 
573 static void
coff_swap_lineno_in(bfd * abfd,void * ext1,void * in1)574 coff_swap_lineno_in (bfd * abfd, void * ext1, void * in1)
575 {
576   LINENO *ext = (LINENO *) ext1;
577   struct internal_lineno *in = (struct internal_lineno *) in1;
578 
579   in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx);
580   in->l_lnno = GET_LINENO_LNNO (abfd, ext);
581 }
582 
583 static unsigned int
coff_swap_lineno_out(bfd * abfd,void * inp,void * outp)584 coff_swap_lineno_out (bfd * abfd, void * inp, void * outp)
585 {
586   struct internal_lineno *in = (struct internal_lineno *) inp;
587   struct external_lineno *ext = (struct external_lineno *) outp;
588   H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx);
589 
590   PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
591   return LINESZ;
592 }
593 
594 #endif /* NO_COFF_LINENOS */
595 
596 static void
coff_swap_aouthdr_in(bfd * abfd,void * aouthdr_ext1,void * aouthdr_int1)597 coff_swap_aouthdr_in (bfd * abfd, void * aouthdr_ext1, void * aouthdr_int1)
598 {
599   AOUTHDR *aouthdr_ext;
600   struct internal_aouthdr *aouthdr_int;
601 
602   aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
603   aouthdr_int = (struct internal_aouthdr *) aouthdr_int1;
604   aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic);
605   aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp);
606   aouthdr_int->tsize = GET_AOUTHDR_TSIZE (abfd, aouthdr_ext->tsize);
607   aouthdr_int->dsize = GET_AOUTHDR_DSIZE (abfd, aouthdr_ext->dsize);
608   aouthdr_int->bsize = GET_AOUTHDR_BSIZE (abfd, aouthdr_ext->bsize);
609   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
610   aouthdr_int->text_start =
611     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
612   aouthdr_int->data_start =
613     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
614 
615 #ifdef RS6000COFF_C
616 #ifdef XCOFF64
617   aouthdr_int->o_toc = H_GET_64 (abfd, aouthdr_ext->o_toc);
618 #else
619   aouthdr_int->o_toc = H_GET_32 (abfd, aouthdr_ext->o_toc);
620 #endif
621   aouthdr_int->o_snentry  = H_GET_16 (abfd, aouthdr_ext->o_snentry);
622   aouthdr_int->o_sntext   = H_GET_16 (abfd, aouthdr_ext->o_sntext);
623   aouthdr_int->o_sndata   = H_GET_16 (abfd, aouthdr_ext->o_sndata);
624   aouthdr_int->o_sntoc    = H_GET_16 (abfd, aouthdr_ext->o_sntoc);
625   aouthdr_int->o_snloader = H_GET_16 (abfd, aouthdr_ext->o_snloader);
626   aouthdr_int->o_snbss    = H_GET_16 (abfd, aouthdr_ext->o_snbss);
627   aouthdr_int->o_algntext = H_GET_16 (abfd, aouthdr_ext->o_algntext);
628   aouthdr_int->o_algndata = H_GET_16 (abfd, aouthdr_ext->o_algndata);
629   aouthdr_int->o_modtype  = H_GET_16 (abfd, aouthdr_ext->o_modtype);
630   aouthdr_int->o_cputype  = H_GET_16 (abfd, aouthdr_ext->o_cputype);
631 #ifdef XCOFF64
632   aouthdr_int->o_maxstack = H_GET_64 (abfd, aouthdr_ext->o_maxstack);
633   aouthdr_int->o_maxdata  = H_GET_64 (abfd, aouthdr_ext->o_maxdata);
634 #else
635   aouthdr_int->o_maxstack = H_GET_32 (abfd, aouthdr_ext->o_maxstack);
636   aouthdr_int->o_maxdata  = H_GET_32 (abfd, aouthdr_ext->o_maxdata);
637 #endif
638 #endif
639 
640 #ifdef MIPSECOFF
641   aouthdr_int->bss_start  = H_GET_32 (abfd, aouthdr_ext->bss_start);
642   aouthdr_int->gp_value   = H_GET_32 (abfd, aouthdr_ext->gp_value);
643   aouthdr_int->gprmask    = H_GET_32 (abfd, aouthdr_ext->gprmask);
644   aouthdr_int->cprmask[0] = H_GET_32 (abfd, aouthdr_ext->cprmask[0]);
645   aouthdr_int->cprmask[1] = H_GET_32 (abfd, aouthdr_ext->cprmask[1]);
646   aouthdr_int->cprmask[2] = H_GET_32 (abfd, aouthdr_ext->cprmask[2]);
647   aouthdr_int->cprmask[3] = H_GET_32 (abfd, aouthdr_ext->cprmask[3]);
648 #endif
649 
650 #ifdef ALPHAECOFF
651   aouthdr_int->bss_start = H_GET_64 (abfd, aouthdr_ext->bss_start);
652   aouthdr_int->gp_value  = H_GET_64 (abfd, aouthdr_ext->gp_value);
653   aouthdr_int->gprmask   = H_GET_32 (abfd, aouthdr_ext->gprmask);
654   aouthdr_int->fprmask   = H_GET_32 (abfd, aouthdr_ext->fprmask);
655 #endif
656 }
657 
658 static unsigned int
coff_swap_aouthdr_out(bfd * abfd,void * in,void * out)659 coff_swap_aouthdr_out (bfd * abfd, void * in, void * out)
660 {
661   struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *) in;
662   AOUTHDR *aouthdr_out = (AOUTHDR *) out;
663 
664   H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->magic);
665   H_PUT_16 (abfd, aouthdr_in->vstamp, aouthdr_out->vstamp);
666   PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, aouthdr_out->tsize);
667   PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, aouthdr_out->dsize);
668   PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, aouthdr_out->bsize);
669   PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, aouthdr_out->entry);
670   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
671 			  aouthdr_out->text_start);
672   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
673 			  aouthdr_out->data_start);
674 
675 #ifdef RS6000COFF_C
676 #ifdef XCOFF64
677   H_PUT_64 (abfd, aouthdr_in->o_toc, aouthdr_out->o_toc);
678 #else
679   H_PUT_32 (abfd, aouthdr_in->o_toc, aouthdr_out->o_toc);
680 #endif
681   H_PUT_16 (abfd, aouthdr_in->o_snentry, aouthdr_out->o_snentry);
682   H_PUT_16 (abfd, aouthdr_in->o_sntext, aouthdr_out->o_sntext);
683   H_PUT_16 (abfd, aouthdr_in->o_sndata, aouthdr_out->o_sndata);
684   H_PUT_16 (abfd, aouthdr_in->o_sntoc, aouthdr_out->o_sntoc);
685   H_PUT_16 (abfd, aouthdr_in->o_snloader, aouthdr_out->o_snloader);
686   H_PUT_16 (abfd, aouthdr_in->o_snbss, aouthdr_out->o_snbss);
687   H_PUT_16 (abfd, aouthdr_in->o_algntext, aouthdr_out->o_algntext);
688   H_PUT_16 (abfd, aouthdr_in->o_algndata, aouthdr_out->o_algndata);
689   H_PUT_16 (abfd, aouthdr_in->o_modtype, aouthdr_out->o_modtype);
690   H_PUT_16 (abfd, aouthdr_in->o_cputype, aouthdr_out->o_cputype);
691 #ifdef XCOFF64
692   H_PUT_64 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack);
693   H_PUT_64 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata);
694 #else
695   H_PUT_32 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack);
696   H_PUT_32 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata);
697 #endif
698   /* TODO: set o_*psize dynamically */
699   H_PUT_8 (abfd, 0, aouthdr_out->o_textpsize);
700   H_PUT_8 (abfd, 0, aouthdr_out->o_datapsize);
701   H_PUT_8 (abfd, 0, aouthdr_out->o_stackpsize);
702   H_PUT_8 (abfd, aouthdr_in->o_flags, aouthdr_out->o_flags);
703   H_PUT_16 (abfd, aouthdr_in->o_sntdata, aouthdr_out->o_sntdata);
704   H_PUT_16 (abfd, aouthdr_in->o_sntbss, aouthdr_out->o_sntbss);
705   H_PUT_32 (abfd, 0, aouthdr_out->o_debugger);
706 #ifdef XCOFF64
707   H_PUT_16 (abfd, aouthdr_in->o_x64flags, aouthdr_out->o_x64flags);
708   memset (aouthdr_out->o_resv3, 0, sizeof aouthdr_out->o_resv3);
709 #endif
710 #endif
711 
712 #ifdef MIPSECOFF
713   H_PUT_32 (abfd, aouthdr_in->bss_start, aouthdr_out->bss_start);
714   H_PUT_32 (abfd, aouthdr_in->gp_value, aouthdr_out->gp_value);
715   H_PUT_32 (abfd, aouthdr_in->gprmask, aouthdr_out->gprmask);
716   H_PUT_32 (abfd, aouthdr_in->cprmask[0], aouthdr_out->cprmask[0]);
717   H_PUT_32 (abfd, aouthdr_in->cprmask[1], aouthdr_out->cprmask[1]);
718   H_PUT_32 (abfd, aouthdr_in->cprmask[2], aouthdr_out->cprmask[2]);
719   H_PUT_32 (abfd, aouthdr_in->cprmask[3], aouthdr_out->cprmask[3]);
720 #endif
721 
722 #ifdef ALPHAECOFF
723   /* FIXME: What does bldrev mean?  */
724   H_PUT_16 (abfd, 2, aouthdr_out->bldrev);
725   H_PUT_16 (abfd, 0, aouthdr_out->padding);
726   H_PUT_64 (abfd, aouthdr_in->bss_start, aouthdr_out->bss_start);
727   H_PUT_64 (abfd, aouthdr_in->gp_value, aouthdr_out->gp_value);
728   H_PUT_32 (abfd, aouthdr_in->gprmask, aouthdr_out->gprmask);
729   H_PUT_32 (abfd, aouthdr_in->fprmask, aouthdr_out->fprmask);
730 #endif
731 
732   return AOUTSZ;
733 }
734 
735 ATTRIBUTE_UNUSED
736 static void
coff_swap_scnhdr_in(bfd * abfd,void * ext,void * in)737 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
738 {
739   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
740   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
741 
742 #ifdef COFF_ADJUST_SCNHDR_IN_PRE
743   COFF_ADJUST_SCNHDR_IN_PRE (abfd, ext, in);
744 #endif
745   memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
746 
747   scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
748   scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
749   scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
750 
751   scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
752   scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
753   scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
754   scnhdr_int->s_flags = GET_SCNHDR_FLAGS (abfd, scnhdr_ext->s_flags);
755   scnhdr_int->s_nreloc = GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc);
756   scnhdr_int->s_nlnno = GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
757 #ifdef COFF_ADJUST_SCNHDR_IN_POST
758   COFF_ADJUST_SCNHDR_IN_POST (abfd, ext, in);
759 #endif
760 }
761 
762 ATTRIBUTE_UNUSED
763 static unsigned int
coff_swap_scnhdr_out(bfd * abfd,void * in,void * out)764 coff_swap_scnhdr_out (bfd * abfd, void * in, void * out)
765 {
766   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
767   SCNHDR *scnhdr_ext = (SCNHDR *) out;
768   unsigned int ret = bfd_coff_scnhsz (abfd);
769 
770 #ifdef COFF_ADJUST_SCNHDR_OUT_PRE
771   COFF_ADJUST_SCNHDR_OUT_PRE (abfd, in, out);
772 #endif
773   memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
774 
775   PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr);
776   PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr);
777   PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size, scnhdr_ext->s_size);
778   PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr);
779   PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr);
780   PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr);
781   PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
782   if (scnhdr_int->s_nlnno <= MAX_SCNHDR_NLNNO)
783     PUT_SCNHDR_NLNNO (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
784   else
785     {
786       char buf[sizeof (scnhdr_int->s_name) + 1];
787 
788       memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
789       buf[sizeof (scnhdr_int->s_name)] = '\0';
790       _bfd_error_handler
791 	/* xgettext:c-format */
792 	(_("%pB: warning: %s: line number overflow: 0x%lx > 0xffff"),
793 	 abfd, buf, scnhdr_int->s_nlnno);
794       PUT_SCNHDR_NLNNO (abfd, 0xffff, scnhdr_ext->s_nlnno);
795     }
796 
797   if (scnhdr_int->s_nreloc <= MAX_SCNHDR_NRELOC)
798     PUT_SCNHDR_NRELOC (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
799   else
800     {
801       char buf[sizeof (scnhdr_int->s_name) + 1];
802 
803       memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
804       buf[sizeof (scnhdr_int->s_name)] = '\0';
805       /* xgettext:c-format */
806       _bfd_error_handler (_("%pB: %s: reloc overflow: 0x%lx > 0xffff"),
807 			  abfd, buf, scnhdr_int->s_nreloc);
808       bfd_set_error (bfd_error_file_truncated);
809       PUT_SCNHDR_NRELOC (abfd, 0xffff, scnhdr_ext->s_nreloc);
810       ret = 0;
811     }
812 
813 #ifdef COFF_ADJUST_SCNHDR_OUT_POST
814   COFF_ADJUST_SCNHDR_OUT_POST (abfd, in, out);
815 #endif
816   return ret;
817 }
818