1/* Generic COFF swapping routines, for BFD.
2   Copyright (C) 1990-2022 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
214static void
215coff_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
229static unsigned int
230coff_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#ifdef TICOFF
250static void
251coff_swap_reloc_v0_in (bfd *abfd, void *src, void *dst)
252{
253  struct external_reloc_v0 *reloc_src = (struct external_reloc_v0 *) src;
254  struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
255
256  reloc_dst->r_vaddr  = GET_RELOC_VADDR (abfd, reloc_src->r_vaddr);
257  reloc_dst->r_symndx = H_GET_16 (abfd, reloc_src->r_symndx);
258  reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
259}
260
261static unsigned int
262coff_swap_reloc_v0_out (bfd *abfd, void *src, void *dst)
263{
264  struct internal_reloc *reloc_src = (struct internal_reloc *) src;
265  struct external_reloc_v0 *reloc_dst = (struct external_reloc_v0 *) dst;
266
267  PUT_RELOC_VADDR (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
268  H_PUT_16 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
269  H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
270  SWAP_OUT_RELOC_EXTRA (abfd, reloc_src, reloc_dst);
271
272  return bfd_coff_relsz (abfd);
273}
274#endif
275
276#endif /* NO_COFF_RELOCS */
277
278static void
279coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
280{
281  FILHDR *filehdr_src = (FILHDR *) src;
282  struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
283
284#ifdef COFF_ADJUST_FILEHDR_IN_PRE
285  COFF_ADJUST_FILEHDR_IN_PRE (abfd, src, dst);
286#endif
287  filehdr_dst->f_magic  = H_GET_16 (abfd, filehdr_src->f_magic);
288  filehdr_dst->f_nscns  = H_GET_16 (abfd, filehdr_src->f_nscns);
289  filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->f_timdat);
290  filehdr_dst->f_symptr = GET_FILEHDR_SYMPTR (abfd, filehdr_src->f_symptr);
291  filehdr_dst->f_nsyms  = H_GET_32 (abfd, filehdr_src->f_nsyms);
292  filehdr_dst->f_opthdr = H_GET_16 (abfd, filehdr_src->f_opthdr);
293  filehdr_dst->f_flags  = H_GET_16 (abfd, filehdr_src->f_flags);
294
295#ifdef COFF_ADJUST_FILEHDR_IN_POST
296  COFF_ADJUST_FILEHDR_IN_POST (abfd, src, dst);
297#endif
298}
299
300static  unsigned int
301coff_swap_filehdr_out (bfd *abfd, void * in, void * out)
302{
303  struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
304  FILHDR *filehdr_out = (FILHDR *) out;
305
306#ifdef COFF_ADJUST_FILEHDR_OUT_PRE
307  COFF_ADJUST_FILEHDR_OUT_PRE (abfd, in, out);
308#endif
309  H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
310  H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns);
311  H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->f_timdat);
312  PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr);
313  H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms);
314  H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr);
315  H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags);
316
317#ifdef COFF_ADJUST_FILEHDR_OUT_POST
318  COFF_ADJUST_FILEHDR_OUT_POST (abfd, in, out);
319#endif
320  return bfd_coff_filhsz (abfd);
321}
322
323#ifndef NO_COFF_SYMBOLS
324
325static void
326coff_swap_sym_in (bfd * abfd, void * ext1, void * in1)
327{
328  SYMENT *ext = (SYMENT *) ext1;
329  struct internal_syment *in = (struct internal_syment *) in1;
330
331  if (ext->e.e_name[0] == 0)
332    {
333      in->_n._n_n._n_zeroes = 0;
334      in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset);
335    }
336  else
337    {
338#if SYMNMLEN != E_SYMNMLEN
339#error we need to cope with truncating or extending SYMNMLEN
340#else
341      memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN);
342#endif
343    }
344
345  in->n_value = H_GET_32 (abfd, ext->e_value);
346  in->n_scnum = (short) H_GET_16 (abfd, ext->e_scnum);
347  if (sizeof (ext->e_type) == 2)
348    in->n_type = H_GET_16 (abfd, ext->e_type);
349  else
350    in->n_type = H_GET_32 (abfd, ext->e_type);
351  in->n_sclass = H_GET_8 (abfd, ext->e_sclass);
352  in->n_numaux = H_GET_8 (abfd, ext->e_numaux);
353#ifdef COFF_ADJUST_SYM_IN_POST
354  COFF_ADJUST_SYM_IN_POST (abfd, ext1, in1);
355#endif
356}
357
358static unsigned int
359coff_swap_sym_out (bfd * abfd, void * inp, void * extp)
360{
361  struct internal_syment *in = (struct internal_syment *) inp;
362  SYMENT *ext =(SYMENT *) extp;
363
364#ifdef COFF_ADJUST_SYM_OUT_PRE
365  COFF_ADJUST_SYM_OUT_PRE (abfd, inp, extp);
366#endif
367
368  if (in->_n._n_name[0] == 0)
369    {
370      H_PUT_32 (abfd, 0, ext->e.e.e_zeroes);
371      H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset);
372    }
373  else
374    {
375#if SYMNMLEN != E_SYMNMLEN
376#error we need to cope with truncating or extending SYMNMLEN
377#else
378      memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN);
379#endif
380    }
381
382  H_PUT_32 (abfd, in->n_value, ext->e_value);
383  H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);
384
385  if (sizeof (ext->e_type) == 2)
386    H_PUT_16 (abfd, in->n_type, ext->e_type);
387  else
388    H_PUT_32 (abfd, in->n_type, ext->e_type);
389
390  H_PUT_8 (abfd, in->n_sclass, ext->e_sclass);
391  H_PUT_8 (abfd, in->n_numaux, ext->e_numaux);
392
393#ifdef COFF_ADJUST_SYM_OUT_POST
394  COFF_ADJUST_SYM_OUT_POST (abfd, inp, extp);
395#endif
396
397  return SYMESZ;
398}
399
400static void
401coff_swap_aux_in (bfd *abfd,
402		  void * ext1,
403		  int type,
404		  int in_class,
405		  int indx,
406		  int numaux,
407		  void * in1)
408{
409  AUXENT *ext = (AUXENT *) ext1;
410  union internal_auxent *in = (union internal_auxent *) in1;
411
412#ifdef COFF_ADJUST_AUX_IN_PRE
413  COFF_ADJUST_AUX_IN_PRE (abfd, ext1, type, in_class, indx, numaux, in1);
414#endif
415
416  switch (in_class)
417    {
418    case C_FILE:
419      if (ext->x_file.x_fname[0] == 0)
420	{
421	  in->x_file.x_n.x_n.x_zeroes = 0;
422	  in->x_file.x_n.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
423	}
424      else
425	{
426#if FILNMLEN != E_FILNMLEN
427#error we need to cope with truncating or extending FILNMLEN
428#else
429	  if (numaux > 1 && coff_data (abfd)->pe)
430	    {
431	      if (indx == 0)
432		memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname,
433			numaux * sizeof (AUXENT));
434	    }
435	  else
436	    memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname, FILNMLEN);
437#endif
438	}
439      goto end;
440
441    case C_STAT:
442#ifdef C_LEAFSTAT
443    case C_LEAFSTAT:
444#endif
445    case C_HIDDEN:
446      if (type == T_NULL)
447	{
448	  in->x_scn.x_scnlen = GET_SCN_SCNLEN (abfd, ext);
449	  in->x_scn.x_nreloc = GET_SCN_NRELOC (abfd, ext);
450	  in->x_scn.x_nlinno = GET_SCN_NLINNO (abfd, ext);
451
452	  /* PE defines some extra fields; we zero them out for
453	     safety.  */
454	  in->x_scn.x_checksum = 0;
455	  in->x_scn.x_associated = 0;
456	  in->x_scn.x_comdat = 0;
457
458	  goto end;
459	}
460      break;
461    }
462
463  in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
464#ifndef NO_TVNDX
465  in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
466#endif
467
468  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
469      || ISTAG (in_class))
470    {
471      in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
472      in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
473    }
474  else
475    {
476#if DIMNUM != E_DIMNUM
477#error we need to cope with truncating or extending DIMNUM
478#endif
479      in->x_sym.x_fcnary.x_ary.x_dimen[0] =
480	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
481      in->x_sym.x_fcnary.x_ary.x_dimen[1] =
482	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
483      in->x_sym.x_fcnary.x_ary.x_dimen[2] =
484	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
485      in->x_sym.x_fcnary.x_ary.x_dimen[3] =
486	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
487    }
488
489  if (ISFCN (type))
490    in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize);
491  else
492    {
493      in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO (abfd, ext);
494      in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE (abfd, ext);
495    }
496
497 end: ;
498
499#ifdef COFF_ADJUST_AUX_IN_POST
500  COFF_ADJUST_AUX_IN_POST (abfd, ext1, type, in_class, indx, numaux, in1);
501#endif
502}
503
504static unsigned int
505coff_swap_aux_out (bfd * abfd,
506		   void * inp,
507		   int type,
508		   int in_class,
509		   int indx ATTRIBUTE_UNUSED,
510		   int numaux ATTRIBUTE_UNUSED,
511		   void * extp)
512{
513  union internal_auxent * in = (union internal_auxent *) inp;
514  AUXENT *ext = (AUXENT *) extp;
515
516#ifdef COFF_ADJUST_AUX_OUT_PRE
517  COFF_ADJUST_AUX_OUT_PRE (abfd, inp, type, in_class, indx, numaux, extp);
518#endif
519
520  memset (ext, 0, AUXESZ);
521
522  switch (in_class)
523    {
524    case C_FILE:
525      if (in->x_file.x_n.x_fname[0] == 0)
526	{
527	  H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
528	  H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset, ext->x_file.x_n.x_offset);
529	}
530      else
531	{
532#if FILNMLEN != E_FILNMLEN
533#error we need to cope with truncating or extending FILNMLEN
534#else
535	  memcpy (ext->x_file.x_fname, in->x_file.x_n.x_fname, FILNMLEN);
536#endif
537	}
538      goto end;
539
540    case C_STAT:
541#ifdef C_LEAFSTAT
542    case C_LEAFSTAT:
543#endif
544    case C_HIDDEN:
545      if (type == T_NULL)
546	{
547	  PUT_SCN_SCNLEN (abfd, in->x_scn.x_scnlen, ext);
548	  PUT_SCN_NRELOC (abfd, in->x_scn.x_nreloc, ext);
549	  PUT_SCN_NLINNO (abfd, in->x_scn.x_nlinno, ext);
550	  goto end;
551	}
552      break;
553    }
554
555  H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
556#ifndef NO_TVNDX
557  H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
558#endif
559
560  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
561      || ISTAG (in_class))
562    {
563      PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
564      PUT_FCN_ENDNDX (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
565    }
566  else
567    {
568#if DIMNUM != E_DIMNUM
569#error we need to cope with truncating or extending DIMNUM
570#endif
571      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
572	       ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
573      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
574	       ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
575      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
576	       ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
577      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
578	       ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
579    }
580
581  if (ISFCN (type))
582    H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize);
583  else
584    {
585      PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
586      PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
587    }
588
589 end:
590#ifdef COFF_ADJUST_AUX_OUT_POST
591  COFF_ADJUST_AUX_OUT_POST (abfd, inp, type, in_class, indx, numaux, extp);
592#endif
593  return AUXESZ;
594}
595
596#endif /* NO_COFF_SYMBOLS */
597
598#ifndef NO_COFF_LINENOS
599
600static void
601coff_swap_lineno_in (bfd * abfd, void * ext1, void * in1)
602{
603  LINENO *ext = (LINENO *) ext1;
604  struct internal_lineno *in = (struct internal_lineno *) in1;
605
606  in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx);
607  in->l_lnno = GET_LINENO_LNNO (abfd, ext);
608}
609
610static unsigned int
611coff_swap_lineno_out (bfd * abfd, void * inp, void * outp)
612{
613  struct internal_lineno *in = (struct internal_lineno *) inp;
614  struct external_lineno *ext = (struct external_lineno *) outp;
615  H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx);
616
617  PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
618  return LINESZ;
619}
620
621#endif /* NO_COFF_LINENOS */
622
623static void
624coff_swap_aouthdr_in (bfd * abfd, void * aouthdr_ext1, void * aouthdr_int1)
625{
626  AOUTHDR *aouthdr_ext;
627  struct internal_aouthdr *aouthdr_int;
628
629  aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
630  aouthdr_int = (struct internal_aouthdr *) aouthdr_int1;
631  aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic);
632  aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp);
633  aouthdr_int->tsize = GET_AOUTHDR_TSIZE (abfd, aouthdr_ext->tsize);
634  aouthdr_int->dsize = GET_AOUTHDR_DSIZE (abfd, aouthdr_ext->dsize);
635  aouthdr_int->bsize = GET_AOUTHDR_BSIZE (abfd, aouthdr_ext->bsize);
636  aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
637  aouthdr_int->text_start =
638    GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
639  aouthdr_int->data_start =
640    GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
641
642#ifdef RS6000COFF_C
643#ifdef XCOFF64
644  aouthdr_int->o_toc = H_GET_64 (abfd, aouthdr_ext->o_toc);
645#else
646  aouthdr_int->o_toc = H_GET_32 (abfd, aouthdr_ext->o_toc);
647#endif
648  aouthdr_int->o_snentry  = H_GET_16 (abfd, aouthdr_ext->o_snentry);
649  aouthdr_int->o_sntext   = H_GET_16 (abfd, aouthdr_ext->o_sntext);
650  aouthdr_int->o_sndata   = H_GET_16 (abfd, aouthdr_ext->o_sndata);
651  aouthdr_int->o_sntoc    = H_GET_16 (abfd, aouthdr_ext->o_sntoc);
652  aouthdr_int->o_snloader = H_GET_16 (abfd, aouthdr_ext->o_snloader);
653  aouthdr_int->o_snbss    = H_GET_16 (abfd, aouthdr_ext->o_snbss);
654  aouthdr_int->o_algntext = H_GET_16 (abfd, aouthdr_ext->o_algntext);
655  aouthdr_int->o_algndata = H_GET_16 (abfd, aouthdr_ext->o_algndata);
656  aouthdr_int->o_modtype  = H_GET_16 (abfd, aouthdr_ext->o_modtype);
657  aouthdr_int->o_cputype  = H_GET_16 (abfd, aouthdr_ext->o_cputype);
658#ifdef XCOFF64
659  aouthdr_int->o_maxstack = H_GET_64 (abfd, aouthdr_ext->o_maxstack);
660  aouthdr_int->o_maxdata  = H_GET_64 (abfd, aouthdr_ext->o_maxdata);
661#else
662  aouthdr_int->o_maxstack = H_GET_32 (abfd, aouthdr_ext->o_maxstack);
663  aouthdr_int->o_maxdata  = H_GET_32 (abfd, aouthdr_ext->o_maxdata);
664#endif
665#endif
666
667#ifdef MIPSECOFF
668  aouthdr_int->bss_start  = H_GET_32 (abfd, aouthdr_ext->bss_start);
669  aouthdr_int->gp_value   = H_GET_32 (abfd, aouthdr_ext->gp_value);
670  aouthdr_int->gprmask    = H_GET_32 (abfd, aouthdr_ext->gprmask);
671  aouthdr_int->cprmask[0] = H_GET_32 (abfd, aouthdr_ext->cprmask[0]);
672  aouthdr_int->cprmask[1] = H_GET_32 (abfd, aouthdr_ext->cprmask[1]);
673  aouthdr_int->cprmask[2] = H_GET_32 (abfd, aouthdr_ext->cprmask[2]);
674  aouthdr_int->cprmask[3] = H_GET_32 (abfd, aouthdr_ext->cprmask[3]);
675#endif
676
677#ifdef ALPHAECOFF
678  aouthdr_int->bss_start = H_GET_64 (abfd, aouthdr_ext->bss_start);
679  aouthdr_int->gp_value  = H_GET_64 (abfd, aouthdr_ext->gp_value);
680  aouthdr_int->gprmask   = H_GET_32 (abfd, aouthdr_ext->gprmask);
681  aouthdr_int->fprmask   = H_GET_32 (abfd, aouthdr_ext->fprmask);
682#endif
683}
684
685static unsigned int
686coff_swap_aouthdr_out (bfd * abfd, void * in, void * out)
687{
688  struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *) in;
689  AOUTHDR *aouthdr_out = (AOUTHDR *) out;
690
691  H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->magic);
692  H_PUT_16 (abfd, aouthdr_in->vstamp, aouthdr_out->vstamp);
693  PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, aouthdr_out->tsize);
694  PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, aouthdr_out->dsize);
695  PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, aouthdr_out->bsize);
696  PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, aouthdr_out->entry);
697  PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
698			  aouthdr_out->text_start);
699  PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
700			  aouthdr_out->data_start);
701
702#ifdef RS6000COFF_C
703#ifdef XCOFF64
704  H_PUT_64 (abfd, aouthdr_in->o_toc, aouthdr_out->o_toc);
705#else
706  H_PUT_32 (abfd, aouthdr_in->o_toc, aouthdr_out->o_toc);
707#endif
708  H_PUT_16 (abfd, aouthdr_in->o_snentry, aouthdr_out->o_snentry);
709  H_PUT_16 (abfd, aouthdr_in->o_sntext, aouthdr_out->o_sntext);
710  H_PUT_16 (abfd, aouthdr_in->o_sndata, aouthdr_out->o_sndata);
711  H_PUT_16 (abfd, aouthdr_in->o_sntoc, aouthdr_out->o_sntoc);
712  H_PUT_16 (abfd, aouthdr_in->o_snloader, aouthdr_out->o_snloader);
713  H_PUT_16 (abfd, aouthdr_in->o_snbss, aouthdr_out->o_snbss);
714  H_PUT_16 (abfd, aouthdr_in->o_algntext, aouthdr_out->o_algntext);
715  H_PUT_16 (abfd, aouthdr_in->o_algndata, aouthdr_out->o_algndata);
716  H_PUT_16 (abfd, aouthdr_in->o_modtype, aouthdr_out->o_modtype);
717  H_PUT_16 (abfd, aouthdr_in->o_cputype, aouthdr_out->o_cputype);
718#ifdef XCOFF64
719  H_PUT_64 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack);
720  H_PUT_64 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata);
721#else
722  H_PUT_32 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack);
723  H_PUT_32 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata);
724#endif
725  /* TODO: set o_*psize dynamically */
726  H_PUT_8 (abfd, 0, aouthdr_out->o_textpsize);
727  H_PUT_8 (abfd, 0, aouthdr_out->o_datapsize);
728  H_PUT_8 (abfd, 0, aouthdr_out->o_stackpsize);
729  H_PUT_8 (abfd, aouthdr_in->o_flags, aouthdr_out->o_flags);
730  H_PUT_16 (abfd, aouthdr_in->o_sntdata, aouthdr_out->o_sntdata);
731  H_PUT_16 (abfd, aouthdr_in->o_sntbss, aouthdr_out->o_sntbss);
732  H_PUT_32 (abfd, 0, aouthdr_out->o_debugger);
733#ifdef XCOFF64
734  H_PUT_16 (abfd, aouthdr_in->o_x64flags, aouthdr_out->o_x64flags);
735  memset (aouthdr_out->o_resv3, 0, sizeof aouthdr_out->o_resv3);
736#endif
737#endif
738
739#ifdef MIPSECOFF
740  H_PUT_32 (abfd, aouthdr_in->bss_start, aouthdr_out->bss_start);
741  H_PUT_32 (abfd, aouthdr_in->gp_value, aouthdr_out->gp_value);
742  H_PUT_32 (abfd, aouthdr_in->gprmask, aouthdr_out->gprmask);
743  H_PUT_32 (abfd, aouthdr_in->cprmask[0], aouthdr_out->cprmask[0]);
744  H_PUT_32 (abfd, aouthdr_in->cprmask[1], aouthdr_out->cprmask[1]);
745  H_PUT_32 (abfd, aouthdr_in->cprmask[2], aouthdr_out->cprmask[2]);
746  H_PUT_32 (abfd, aouthdr_in->cprmask[3], aouthdr_out->cprmask[3]);
747#endif
748
749#ifdef ALPHAECOFF
750  /* FIXME: What does bldrev mean?  */
751  H_PUT_16 (abfd, 2, aouthdr_out->bldrev);
752  H_PUT_16 (abfd, 0, aouthdr_out->padding);
753  H_PUT_64 (abfd, aouthdr_in->bss_start, aouthdr_out->bss_start);
754  H_PUT_64 (abfd, aouthdr_in->gp_value, aouthdr_out->gp_value);
755  H_PUT_32 (abfd, aouthdr_in->gprmask, aouthdr_out->gprmask);
756  H_PUT_32 (abfd, aouthdr_in->fprmask, aouthdr_out->fprmask);
757#endif
758
759  return AOUTSZ;
760}
761
762ATTRIBUTE_UNUSED
763static void
764coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
765{
766  SCNHDR *scnhdr_ext = (SCNHDR *) ext;
767  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
768
769#ifdef COFF_ADJUST_SCNHDR_IN_PRE
770  COFF_ADJUST_SCNHDR_IN_PRE (abfd, ext, in);
771#endif
772  memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
773
774  scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
775  scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
776  scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
777
778  scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
779  scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
780  scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
781  scnhdr_int->s_flags = GET_SCNHDR_FLAGS (abfd, scnhdr_ext->s_flags);
782  scnhdr_int->s_nreloc = GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc);
783  scnhdr_int->s_nlnno = GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
784#ifdef COFF_ADJUST_SCNHDR_IN_POST
785  COFF_ADJUST_SCNHDR_IN_POST (abfd, ext, in);
786#endif
787}
788
789ATTRIBUTE_UNUSED
790static unsigned int
791coff_swap_scnhdr_out (bfd * abfd, void * in, void * out)
792{
793  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
794  SCNHDR *scnhdr_ext = (SCNHDR *) out;
795  unsigned int ret = bfd_coff_scnhsz (abfd);
796
797#ifdef COFF_ADJUST_SCNHDR_OUT_PRE
798  COFF_ADJUST_SCNHDR_OUT_PRE (abfd, in, out);
799#endif
800  memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
801
802  PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr);
803  PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr);
804  PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size, scnhdr_ext->s_size);
805  PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr);
806  PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr);
807  PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr);
808  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
809  if (scnhdr_int->s_nlnno <= MAX_SCNHDR_NLNNO)
810    PUT_SCNHDR_NLNNO (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
811  else
812    {
813      char buf[sizeof (scnhdr_int->s_name) + 1];
814
815      memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
816      buf[sizeof (scnhdr_int->s_name)] = '\0';
817      _bfd_error_handler
818	/* xgettext:c-format */
819	(_("%pB: warning: %s: line number overflow: 0x%lx > 0xffff"),
820	 abfd, buf, scnhdr_int->s_nlnno);
821      PUT_SCNHDR_NLNNO (abfd, 0xffff, scnhdr_ext->s_nlnno);
822    }
823
824  if (scnhdr_int->s_nreloc <= MAX_SCNHDR_NRELOC)
825    PUT_SCNHDR_NRELOC (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
826  else
827    {
828      char buf[sizeof (scnhdr_int->s_name) + 1];
829
830      memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
831      buf[sizeof (scnhdr_int->s_name)] = '\0';
832      /* xgettext:c-format */
833      _bfd_error_handler (_("%pB: %s: reloc overflow: 0x%lx > 0xffff"),
834			  abfd, buf, scnhdr_int->s_nreloc);
835      bfd_set_error (bfd_error_file_truncated);
836      PUT_SCNHDR_NRELOC (abfd, 0xffff, scnhdr_ext->s_nreloc);
837      ret = 0;
838    }
839
840#ifdef COFF_ADJUST_SCNHDR_OUT_POST
841  COFF_ADJUST_SCNHDR_OUT_POST (abfd, in, out);
842#endif
843  return ret;
844}
845