1 /* Routines to link ECOFF debugging information.
2 Copyright 1993 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
10 (at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "coff/internal.h"
26 #include "coff/symconst.h"
27 #include "coff/ecoff.h"
29 static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend,
31 static bfd_size_type ecoff_add_string PARAMS ((struct ecoff_debug_info *,
32 FDR *fdr, const char *string));
33 static void ecoff_align_debug PARAMS ((bfd *abfd,
34 struct ecoff_debug_info *debug,
35 const struct ecoff_debug_swap *swap));
37 /* The minimum amount of data to allocate. */
38 #define ALLOC_SIZE (4064)
40 /* Add bytes to a buffer. Return success. */
43 ecoff_add_bytes (buf, bufend, need)
52 have = *bufend - *buf;
58 if (want < ALLOC_SIZE)
62 newbuf = (char *) malloc (have + want);
64 newbuf = (char *) realloc (*buf, have + want);
67 bfd_error = no_memory;
71 *bufend = *buf + have + want;
75 /* Accumulate the debugging information from INPUT_BFD into
76 OUTPUT_BFD. The INPUT_DEBUG argument points to some ECOFF
77 debugging information which we want to link into the information
78 pointed to by the OUTPUT_DEBUG argument. OUTPUT_SWAP and
79 INPUT_SWAP point to the swapping information needed. */
82 bfd_ecoff_debug_accumulate (output_bfd, output_debug, output_swap,
83 input_bfd, input_debug, input_swap,
86 struct ecoff_debug_info *output_debug;
87 const struct ecoff_debug_swap *output_swap;
89 struct ecoff_debug_info *input_debug;
90 const struct ecoff_debug_swap *input_swap;
93 void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
94 = input_swap->swap_sym_in;
95 void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
96 = output_swap->swap_sym_out;
97 void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
98 = output_swap->swap_fdr_out;
99 void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR))
100 = output_swap->swap_rfd_out;
103 bfd_vma section_adjust[scMax];
110 bfd_size_type fdr_add;
113 output_symhdr = &output_debug->symbolic_header;
114 input_symhdr = &input_debug->symbolic_header;
116 /* Make sure the buffers are large enough. */
117 #define CHECK(start, end, count, size) \
118 if ((char *) output_debug->end - (char *) output_debug->start \
119 < (output_symhdr->count + input_symhdr->count) * size) \
121 if (! ecoff_add_bytes ((char **) &output_debug->start, \
122 (char **) &output_debug->end, \
123 ((output_symhdr->count \
124 + input_symhdr->count) \
129 CHECK (line, line_end, cbLine, sizeof (unsigned char));
131 /* I don't think dense number information is needed. */
132 CHECK (external_dnr, external_dnr_end, idnMax,
133 output_swap->external_dnr_size);
135 CHECK (external_pdr, external_pdr_end, ipdMax,
136 output_swap->external_pdr_size);
137 CHECK (external_sym, external_sym_end, isymMax,
138 output_swap->external_sym_size);
139 CHECK (external_opt, external_opt_end, ioptMax,
140 output_swap->external_opt_size);
141 CHECK (external_aux, external_aux_end, iauxMax,
142 sizeof (union aux_ext));
143 CHECK (ss, ss_end, issMax, sizeof (char));
144 CHECK (external_fdr, external_fdr_end, ifdMax,
145 output_swap->external_fdr_size);
147 /* The RFD's are special, since we create them if needed. */
151 crfd = input_symhdr->crfd;
152 if (input_symhdr->crfd == 0)
153 input_symhdr->crfd = input_symhdr->ifdMax;
154 CHECK (external_rfd, external_rfd_end, crfd,
155 output_swap->external_rfd_size);
156 input_symhdr->crfd = crfd;
161 /* Use section_adjust to hold the value to add to a symbol in a
162 particular section. */
163 memset ((PTR) section_adjust, 0, sizeof section_adjust);
165 #define SET(name, indx) \
166 sec = bfd_get_section_by_name (input_bfd, name); \
168 section_adjust[indx] = (sec->output_section->vma \
169 + sec->output_offset \
172 SET (".text", scText);
173 SET (".data", scData);
175 SET (".sdata", scSData);
176 SET (".sbss", scSBss);
177 /* scRdata section may be either .rdata or .rodata. */
178 SET (".rdata", scRData);
179 SET (".rodata", scRData);
180 SET (".init", scInit);
181 SET (".fini", scFini);
185 /* Swap in the local symbols, adjust their values, and swap them out
186 again. The external symbols are handled separately. */
187 sym_out = ((char *) output_debug->external_sym
188 + output_symhdr->isymMax * output_swap->external_sym_size);
189 lraw_src = (char *) input_debug->external_sym;
190 lraw_end = lraw_src + input_symhdr->isymMax * input_swap->external_sym_size;
191 for (; lraw_src < lraw_end; lraw_src += input_swap->external_sym_size)
195 (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym);
197 BFD_ASSERT (internal_sym.sc != scCommon
198 && internal_sym.sc != scSCommon);
200 /* Adjust the symbol value if appropriate. */
201 switch (internal_sym.st)
204 if (ECOFF_IS_STAB (&internal_sym))
212 internal_sym.value += section_adjust[internal_sym.sc];
219 (*swap_sym_out) (output_bfd, &internal_sym, sym_out);
220 sym_out += output_swap->external_sym_size;
223 /* Copy the information that does not need swapping. */
224 memcpy (output_debug->line + output_symhdr->cbLine,
226 input_symhdr->cbLine * sizeof (unsigned char));
227 memcpy (output_debug->external_aux + output_symhdr->iauxMax,
228 input_debug->external_aux,
229 input_symhdr->iauxMax * sizeof (union aux_ext));
230 memcpy (output_debug->ss + output_symhdr->issMax,
232 input_symhdr->issMax * sizeof (char));
234 /* Some of the information may need to be swapped. */
235 if (output_bfd->xvec->header_byteorder_big_p
236 == input_bfd->xvec->header_byteorder_big_p)
238 /* The two BFD's have the same endianness, so memcpy will
241 /* I don't think dense number information is needed. */
242 BFD_ASSERT (output_swap->external_dnr_size
243 == input_swap->external_dnr_size);
244 if (input_symhdr->idnMax > 0)
245 memcpy (((char *) output_debug->external_dnr
246 + output_symhdr->idnMax * output_swap->external_dnr_size),
247 input_debug->external_dnr,
248 input_symhdr->idnMax * output_swap->external_dnr_size);
250 BFD_ASSERT (output_swap->external_pdr_size
251 == input_swap->external_pdr_size);
252 if (input_symhdr->ipdMax > 0)
253 memcpy (((char *) output_debug->external_pdr
254 + output_symhdr->ipdMax * output_swap->external_pdr_size),
255 input_debug->external_pdr,
256 input_symhdr->ipdMax * output_swap->external_pdr_size);
257 BFD_ASSERT (output_swap->external_opt_size
258 == input_swap->external_opt_size);
259 if (input_symhdr->ioptMax > 0)
260 memcpy (((char *) output_debug->external_opt
261 + output_symhdr->ioptMax * output_swap->external_opt_size),
262 input_debug->external_opt,
263 input_symhdr->ioptMax * output_swap->external_opt_size);
267 bfd_size_type outsz, insz;
272 /* The two BFD's have different endianness, so we must swap
273 everything in and out. This code would always work, but it
274 would be slow in the normal case. */
276 /* I don't think dense number information is needed. */
277 outsz = output_swap->external_dnr_size;
278 insz = input_swap->external_dnr_size;
279 in = (char *) input_debug->external_dnr;
280 end = in + input_symhdr->idnMax * insz;
281 out = ((char *) output_debug->external_dnr
282 + output_symhdr->idnMax * outsz);
283 for (; in < end; in += insz, out += outsz)
287 (*input_swap->swap_dnr_in) (input_bfd, in, &dnr);
288 (*output_swap->swap_dnr_out) (output_bfd, &dnr, out);
292 outsz = output_swap->external_pdr_size;
293 insz = input_swap->external_pdr_size;
294 in = (char *) input_debug->external_pdr;
295 end = in + input_symhdr->ipdMax * insz;
296 out = ((char *) output_debug->external_pdr
297 + output_symhdr->ipdMax * outsz);
298 for (; in < end; in += insz, out += outsz)
302 (*input_swap->swap_pdr_in) (input_bfd, in, &pdr);
303 (*output_swap->swap_pdr_out) (output_bfd, &pdr, out);
306 outsz = output_swap->external_opt_size;
307 insz = input_swap->external_opt_size;
308 in = (char *) input_debug->external_opt;
309 end = in + input_symhdr->ioptMax * insz;
310 out = ((char *) output_debug->external_opt
311 + output_symhdr->ioptMax * outsz);
312 for (; in < end; in += insz, out += outsz)
316 (*input_swap->swap_opt_in) (input_bfd, in, &opt);
317 (*output_swap->swap_opt_out) (output_bfd, &opt, out);
321 /* Set ifdbase so that the external symbols know how to adjust their
323 input_debug->ifdbase = output_symhdr->ifdMax;
325 /* We need to handle the FDR's whether they are swapped or not. */
326 if (input_debug->fdr != (FDR *) NULL)
328 fdr_ptr = (char *) input_debug->fdr;
329 fdr_add = sizeof (FDR);
333 fdr_ptr = (char *) input_debug->external_fdr;
334 fdr_add = input_swap->external_fdr_size;
336 fdr_end = fdr_ptr + input_symhdr->ifdMax * fdr_add;
337 fdr_out = ((char *) output_debug->external_fdr
338 + output_symhdr->ifdMax * output_swap->external_fdr_size);
341 fdr_ptr += fdr_add, fdr_out += output_swap->external_fdr_size)
345 if (input_debug->fdr != (FDR *) NULL)
346 fdr = *(FDR *) fdr_ptr;
348 (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
350 /* FIXME: It is conceivable that this FDR points to the .init or
351 .fini section, in which case this will not do the right
353 fdr.adr += section_adjust[scText];
355 fdr.issBase += output_symhdr->issMax;
356 fdr.isymBase += output_symhdr->isymMax;
357 fdr.ilineBase += output_symhdr->ilineMax;
358 fdr.ioptBase += output_symhdr->ioptMax;
359 fdr.ipdFirst += output_symhdr->ipdMax;
360 fdr.iauxBase += output_symhdr->iauxMax;
361 fdr.rfdBase += output_symhdr->crfd;
363 /* If there are no RFD's, we are going to add some. We don't
364 want to adjust crfd for this, so that all the FDR's can share
366 if (input_symhdr->crfd == 0)
367 fdr.crfd = input_symhdr->ifdMax;
370 fdr.cbLineOffset += output_symhdr->cbLine;
372 (*swap_fdr_out) (output_bfd, &fdr, fdr_out);
375 if (input_symhdr->crfd > 0)
377 void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
378 = input_swap->swap_rfd_in;
379 bfd_size_type outsz, insz;
384 /* Swap and adjust the RFD's. RFD's are only created by the
385 linker, so this will only be necessary if one of the input
386 files is the result of a partial link. Presumably all
387 necessary RFD's are present. */
388 outsz = output_swap->external_rfd_size;
389 insz = input_swap->external_rfd_size;
390 rfd_in = (char *) input_debug->external_rfd;
391 rfd_end = rfd_in + input_symhdr->crfd * insz;
392 rfd_out = ((char *) output_debug->external_rfd
393 + output_symhdr->crfd * outsz);
396 rfd_in += insz, rfd_out += outsz)
400 (*swap_rfd_in) (input_bfd, rfd_in, &rfd);
401 rfd += output_symhdr->ifdMax;
402 (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
404 output_symhdr->crfd += input_symhdr->crfd;
413 /* Create RFD's. Some of the debugging information includes
414 relative file indices. These indices are taken as indices to
415 the RFD table if there is one, or to the global table if
416 there is not. If we did not create RFD's, we would have to
417 parse and adjust all the debugging information which contains
419 outsz = output_swap->external_rfd_size;
420 rfd = output_symhdr->ifdMax;
421 rfd_out = ((char *) output_debug->external_rfd
422 + output_symhdr->crfd * outsz);
423 rfd_end = (rfd_out + input_symhdr->ifdMax * outsz);
424 for (; rfd_out < rfd_end; rfd_out += outsz, rfd++)
425 (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
426 output_symhdr->crfd += input_symhdr->ifdMax;
429 /* Update the counts. */
430 output_symhdr->ilineMax += input_symhdr->ilineMax;
431 output_symhdr->cbLine += input_symhdr->cbLine;
433 /* I don't think dense number information is needed. */
434 output_symhdr->idnMax += input_symhdr->idnMax;
436 output_symhdr->ipdMax += input_symhdr->ipdMax;
437 output_symhdr->isymMax += input_symhdr->isymMax;
438 output_symhdr->ioptMax += input_symhdr->ioptMax;
439 output_symhdr->iauxMax += input_symhdr->iauxMax;
440 output_symhdr->issMax += input_symhdr->issMax;
441 output_symhdr->ifdMax += input_symhdr->ifdMax;
446 /* Add a string to the debugging information we are accumulating.
447 Return the offset from the fdr string base. */
450 ecoff_add_string (output, fdr, string)
451 struct ecoff_debug_info *output;
459 symhdr = &output->symbolic_header;
460 len = strlen (string);
461 if (output->ss_end - output->ss < symhdr->issMax + len + 1)
463 if (ecoff_add_bytes (&output->ss, &output->ss_end,
464 symhdr->issMax + len + 1) == false)
467 memcpy (output->ss + symhdr->issMax, string, len + 1);
469 symhdr->issMax += len + 1;
470 fdr->cbSs += len + 1;
474 /* Add debugging information from a non-ECOFF file. */
477 bfd_ecoff_debug_link_other (output_bfd, output_debug, output_swap, input_bfd)
479 struct ecoff_debug_info *output_debug;
480 const struct ecoff_debug_swap *output_swap;
483 void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
484 = output_swap->swap_sym_out;
485 HDRR *output_symhdr = &output_debug->symbolic_header;
492 memset (&fdr, 0, sizeof fdr);
494 sec = bfd_get_section_by_name (input_bfd, ".text");
496 fdr.adr = sec->output_section->vma + sec->output_offset;
499 /* FIXME: What about .init or .fini? */
503 fdr.issBase = output_symhdr->issMax;
505 fdr.rss = ecoff_add_string (output_debug, &fdr,
506 bfd_get_filename (input_bfd));
507 fdr.isymBase = output_symhdr->isymMax;
509 /* Get the local symbols from the input BFD. */
510 symbols = (asymbol **) bfd_alloc (output_bfd,
511 get_symtab_upper_bound (input_bfd));
512 if (symbols == (asymbol **) NULL)
514 bfd_error = no_memory;
517 sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
519 /* Handle the local symbols. Any external symbols are handled
522 for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++)
526 if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
528 memset (&internal_sym, 0, sizeof internal_sym);
529 internal_sym.iss = ecoff_add_string (output_debug, &fdr,
532 if (bfd_is_com_section ((*sym_ptr)->section)
533 || (*sym_ptr)->section == &bfd_und_section)
534 internal_sym.value = (*sym_ptr)->value;
536 internal_sym.value = ((*sym_ptr)->value
537 + (*sym_ptr)->section->output_offset
538 + (*sym_ptr)->section->output_section->vma);
539 internal_sym.st = stNil;
540 internal_sym.sc = scUndefined;
541 internal_sym.index = indexNil;
543 if (((char *) output_debug->external_sym_end
544 - (char *) output_debug->external_sym)
545 < (output_symhdr->isymMax + 1) * output_swap->external_sym_size)
547 if (! ecoff_add_bytes ((char **) &output_debug->external_sym,
548 (char **) &output_debug->external_sym_end,
549 ((output_symhdr->isymMax + 1)
550 * output_swap->external_sym_size)))
554 (*swap_sym_out) (output_bfd, &internal_sym,
555 ((char *) output_debug->external_sym
556 + (output_symhdr->isymMax
557 * output_swap->external_sym_size)));
559 ++output_symhdr->isymMax;
562 bfd_release (output_bfd, (PTR) symbols);
564 if (((char *) output_debug->external_fdr_end
565 - (char *) output_debug->external_fdr)
566 < (output_symhdr->ifdMax + 1) * output_swap->external_fdr_size)
568 if (! ecoff_add_bytes ((char **) &output_debug->external_fdr,
569 (char **) &output_debug->external_fdr_end,
570 ((output_symhdr->ifdMax + 1)
571 * output_swap->external_fdr_size)))
575 /* Leave everything else in the FDR zeroed out. This will cause
576 the lang field to be langC. The fBigendian field will
577 indicate little endian format, but it doesn't matter because
578 it only applies to aux fields and there are none. */
579 (*output_swap->swap_fdr_out)
581 ((char *) output_debug->external_fdr
582 + output_symhdr->ifdMax * output_swap->external_fdr_size));
583 ++output_symhdr->ifdMax;
587 /* Set up ECOFF debugging information for the external symbols. */
590 bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr,
593 struct ecoff_debug_info *debug;
594 const struct ecoff_debug_swap *swap;
595 boolean relocateable;
596 boolean (*get_extr) PARAMS ((asymbol *, EXTR *));
597 void (*set_index) PARAMS ((asymbol *, bfd_size_type));
599 const bfd_size_type external_ext_size = swap->external_ext_size;
600 void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR))
601 = swap->swap_ext_out;
602 HDRR * const symhdr = &debug->symbolic_header;
603 asymbol **sym_ptr_ptr;
606 sym_ptr_ptr = bfd_get_outsymbols (abfd);
607 if (sym_ptr_ptr == NULL)
610 for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++)
615 sym_ptr = *sym_ptr_ptr;
617 /* Get the external symbol information. */
618 if ((*get_extr) (sym_ptr, &esym) == false)
621 /* If we're producing an executable, move common symbols into
623 if (relocateable == false)
625 if (esym.asym.sc == scCommon)
626 esym.asym.sc = scBss;
627 else if (esym.asym.sc == scSCommon)
628 esym.asym.sc = scSBss;
631 if (debug->ssext_end - debug->ssext
632 < symhdr->issExtMax + strlen (sym_ptr->name) + 1)
634 if (ecoff_add_bytes ((char **) &debug->ssext,
635 (char **) &debug->ssext_end,
636 symhdr->issExtMax + strlen (sym_ptr->name) + 1)
640 if ((char *) debug->external_ext_end - (char *) debug->external_ext
641 < (symhdr->iextMax + 1) * external_ext_size)
643 if (ecoff_add_bytes ((char **) &debug->external_ext,
644 (char **) &debug->external_ext_end,
645 (symhdr->iextMax + 1) * external_ext_size)
650 esym.asym.iss = symhdr->issExtMax;
652 if (bfd_is_com_section (sym_ptr->section)
653 || sym_ptr->section == &bfd_und_section)
654 esym.asym.value = sym_ptr->value;
656 esym.asym.value = (sym_ptr->value
657 + sym_ptr->section->output_offset
658 + sym_ptr->section->output_section->vma);
660 (*swap_ext_out) (abfd, &esym,
661 ((char *) debug->external_ext
662 + symhdr->iextMax * swap->external_ext_size));
665 (*set_index) (sym_ptr, symhdr->iextMax);
669 strcpy (debug->ssext + symhdr->issExtMax, sym_ptr->name);
670 symhdr->issExtMax += strlen (sym_ptr->name) + 1;
676 /* Align the ECOFF debugging information. */
679 ecoff_align_debug (abfd, debug, swap)
681 struct ecoff_debug_info *debug;
682 const struct ecoff_debug_swap *swap;
684 HDRR * const symhdr = &debug->symbolic_header;
685 bfd_size_type debug_align, aux_align, add;
687 /* Adjust the counts so that structures are aligned. The alignment
688 of ALLOC_SIZE ensures that we do not have to worry about running
689 off the end of the memory block when doing the memset. */
690 debug_align = swap->debug_align;
691 aux_align = debug_align / sizeof (union aux_ext);
693 add = debug_align - (symhdr->cbLine & (debug_align - 1));
694 if (add != debug_align)
696 memset (debug->line + symhdr->cbLine, 0, add);
697 symhdr->cbLine += add;
700 add = debug_align - (symhdr->issMax & (debug_align - 1));
701 if (add != debug_align)
703 memset (debug->ss + symhdr->issMax, 0, add);
704 symhdr->issMax += add;
707 add = debug_align - (symhdr->issExtMax & (debug_align - 1));
708 if (add != debug_align)
710 memset (debug->ssext + symhdr->issExtMax, 0, add);
711 symhdr->issExtMax += add;
714 add = aux_align - (symhdr->iauxMax & (aux_align - 1));
715 if (add != aux_align)
717 memset (debug->external_aux + symhdr->iauxMax, 0,
718 add * sizeof (union aux_ext));
719 symhdr->iauxMax += add;
723 /* Return the size required by the ECOFF debugging information. */
726 bfd_ecoff_debug_size (abfd, debug, swap)
728 struct ecoff_debug_info *debug;
729 const struct ecoff_debug_swap *swap;
733 ecoff_align_debug (abfd, debug, swap);
734 tot = swap->external_hdr_size;
736 #define ADD(count, size) \
737 tot += debug->symbolic_header.count * size
739 ADD (cbLine, sizeof (unsigned char));
740 ADD (idnMax, swap->external_dnr_size);
741 ADD (ipdMax, swap->external_pdr_size);
742 ADD (isymMax, swap->external_sym_size);
743 ADD (ioptMax, swap->external_opt_size);
744 ADD (iauxMax, sizeof (union aux_ext));
745 ADD (issMax, sizeof (char));
746 ADD (issExtMax, sizeof (char));
747 ADD (ifdMax, swap->external_fdr_size);
748 ADD (crfd, swap->external_rfd_size);
749 ADD (iextMax, swap->external_ext_size);
756 /* Write out the ECOFF debugging information. This function assumes
757 that the information (the pointers and counts) in *DEBUG have been
758 set correctly. WHERE is the position in the file to write the
759 information to. This function fills in the file offsets in the
763 bfd_ecoff_write_debug (abfd, debug, swap, where)
765 struct ecoff_debug_info *debug;
766 const struct ecoff_debug_swap *swap;
769 HDRR * const symhdr = &debug->symbolic_header;
772 ecoff_align_debug (abfd, debug, swap);
774 /* Go to the right location in the file. */
775 if (bfd_seek (abfd, where, SEEK_SET) != 0)
778 where += swap->external_hdr_size;
780 /* Fill in the file offsets. */
781 #define SET(offset, count, size) \
782 if (symhdr->count == 0) \
783 symhdr->offset = 0; \
786 symhdr->offset = where; \
787 where += symhdr->count * size; \
790 SET (cbLineOffset, cbLine, sizeof (unsigned char));
791 SET (cbDnOffset, idnMax, swap->external_dnr_size);
792 SET (cbPdOffset, ipdMax, swap->external_pdr_size);
793 SET (cbSymOffset, isymMax, swap->external_sym_size);
794 SET (cbOptOffset, ioptMax, swap->external_opt_size);
795 SET (cbAuxOffset, iauxMax, sizeof (union aux_ext));
796 SET (cbSsOffset, issMax, sizeof (char));
797 SET (cbSsExtOffset, issExtMax, sizeof (char));
798 SET (cbFdOffset, ifdMax, swap->external_fdr_size);
799 SET (cbRfdOffset, crfd, swap->external_rfd_size);
800 SET (cbExtOffset, iextMax, swap->external_ext_size);
803 buff = (PTR) alloca (swap->external_hdr_size);
804 (*swap->swap_hdr_out) (abfd, symhdr, buff);
805 if (bfd_write (buff, 1, swap->external_hdr_size, abfd)
806 != swap->external_hdr_size)
809 #define WRITE(ptr, count, size, offset) \
810 BFD_ASSERT (symhdr->offset == 0 || bfd_tell (abfd) == symhdr->offset); \
811 if (bfd_write (debug->ptr, size, symhdr->count, abfd) \
812 != size * symhdr->count) \
815 WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset);
816 WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset);
817 WRITE (external_pdr, ipdMax, swap->external_pdr_size, cbPdOffset);
818 WRITE (external_sym, isymMax, swap->external_sym_size, cbSymOffset);
819 WRITE (external_opt, ioptMax, swap->external_opt_size, cbOptOffset);
820 WRITE (external_aux, iauxMax, sizeof (union aux_ext), cbAuxOffset);
821 WRITE (ss, issMax, sizeof (char), cbSsOffset);
822 WRITE (ssext, issExtMax, sizeof (char), cbSsExtOffset);
823 WRITE (external_fdr, ifdMax, swap->external_fdr_size, cbFdOffset);
824 WRITE (external_rfd, crfd, swap->external_rfd_size, cbRfdOffset);
825 WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset);