* ecoff.c: First cut at new style of linker backend for
[external/binutils.git] / bfd / ecofflink.c
1 /* Routines to link ECOFF debugging information.
2    Copyright 1993 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "coff/internal.h"
25 #include "coff/sym.h"
26 #include "coff/symconst.h"
27 #include "coff/ecoff.h"
28 \f
29 static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend,
30                                         size_t need));
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));
36 \f
37 /* The minimum amount of data to allocate.  */
38 #define ALLOC_SIZE (4064)
39
40 /* Add bytes to a buffer.  Return success.  */
41
42 static boolean
43 ecoff_add_bytes (buf, bufend, need)
44      char **buf;
45      char **bufend;
46      size_t need;
47 {
48   size_t have;
49   size_t want;
50   char *newbuf;
51
52   have = *bufend - *buf;
53   if (have > need)
54     want = ALLOC_SIZE;
55   else
56     {
57       want = need - have;
58       if (want < ALLOC_SIZE)
59         want = ALLOC_SIZE;
60     }
61   if (*buf == NULL)
62     newbuf = (char *) malloc (have + want);
63   else
64     newbuf = (char *) realloc (*buf, have + want);
65   if (newbuf == NULL)
66     {
67       bfd_error = no_memory;
68       return false;
69     }
70   *buf = newbuf;
71   *bufend = *buf + have + want;
72   return true;
73 }
74
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.  */
80
81 /*ARGSUSED*/
82 boolean
83 bfd_ecoff_debug_accumulate (output_bfd, output_debug, output_swap,
84                             input_bfd, input_debug, input_swap,
85                             relocateable)
86      bfd *output_bfd;
87      struct ecoff_debug_info *output_debug;
88      const struct ecoff_debug_swap *output_swap;
89      bfd *input_bfd;
90      struct ecoff_debug_info *input_debug;
91      const struct ecoff_debug_swap *input_swap;
92      boolean relocateable;
93 {
94   void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
95     = input_swap->swap_sym_in;
96   void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
97     = output_swap->swap_sym_out;
98   void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
99     = output_swap->swap_fdr_out;
100   void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR))
101     = output_swap->swap_rfd_out;
102   HDRR *output_symhdr;
103   HDRR *input_symhdr;
104   bfd_vma section_adjust[scMax];
105   asection *sec;
106   char *sym_out;
107   char *lraw_src;
108   char *lraw_end;
109   char *fdr_ptr;
110   char *fdr_end;
111   bfd_size_type fdr_add;
112   char *fdr_out;
113
114   output_symhdr = &output_debug->symbolic_header;
115   input_symhdr = &input_debug->symbolic_header;
116
117   /* Make sure the buffers are large enough.  */
118 #define CHECK(start, end, count, size)                          \
119   if ((char *) output_debug->end - (char *) output_debug->start \
120       < (output_symhdr->count + input_symhdr->count) * size)    \
121     {                                                           \
122       if (! ecoff_add_bytes ((char **) &output_debug->start,    \
123                              (char **) &output_debug->end,      \
124                              ((output_symhdr->count             \
125                                + input_symhdr->count)           \
126                               * size)))                         \
127         return false;                                           \
128     }
129
130   CHECK (line, line_end, cbLine, sizeof (unsigned char));
131 #if 0
132   /* I don't think dense number information is needed.  */
133   CHECK (external_dnr, external_dnr_end, idnMax,
134          output_swap->external_dnr_size);
135 #endif
136   CHECK (external_pdr, external_pdr_end, ipdMax,
137          output_swap->external_pdr_size);
138   CHECK (external_sym, external_sym_end, isymMax,
139          output_swap->external_sym_size);
140   CHECK (external_opt, external_opt_end, ioptMax,
141          output_swap->external_opt_size);
142   CHECK (external_aux, external_aux_end, iauxMax,
143          sizeof (union aux_ext));
144   CHECK (ss, ss_end, issMax, sizeof (char));
145   CHECK (external_fdr, external_fdr_end, ifdMax,
146          output_swap->external_fdr_size);
147
148   /* The RFD's are special, since we create them if needed.  */
149   {
150     bfd_size_type crfd;
151
152     crfd = input_symhdr->crfd;
153     if (input_symhdr->crfd == 0)
154       input_symhdr->crfd = input_symhdr->ifdMax;
155     CHECK (external_rfd, external_rfd_end, crfd,
156            output_swap->external_rfd_size);
157     input_symhdr->crfd = crfd;
158   }
159
160 #undef CHECK
161
162   /* Use section_adjust to hold the value to add to a symbol in a
163      particular section.  */
164   memset ((PTR) section_adjust, 0, sizeof section_adjust);
165
166 #define SET(name, indx) \
167   sec = bfd_get_section_by_name (input_bfd, name); \
168   if (sec != NULL) \
169     section_adjust[indx] = (sec->output_section->vma \
170                             + sec->output_offset \
171                             - sec->vma);
172
173   SET (".text", scText);
174   SET (".data", scData);
175   SET (".bss", scBss);
176   SET (".sdata", scSData);
177   SET (".sbss", scSBss);
178   /* scRdata section may be either .rdata or .rodata.  */
179   SET (".rdata", scRData);
180   SET (".rodata", scRData);
181   SET (".init", scInit);
182   SET (".fini", scFini);
183
184 #undef SET
185
186   /* Swap in the local symbols, adjust their values, and swap them out
187      again.  The external symbols are handled separately.  */
188   sym_out = ((char *) output_debug->external_sym
189              + output_symhdr->isymMax * output_swap->external_sym_size);
190   lraw_src = (char *) input_debug->external_sym;
191   lraw_end = lraw_src + input_symhdr->isymMax * input_swap->external_sym_size;
192   for (;  lraw_src < lraw_end;  lraw_src += input_swap->external_sym_size)
193     {
194       SYMR internal_sym;
195
196       (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym);
197
198       BFD_ASSERT (internal_sym.sc != scCommon
199                   && internal_sym.sc != scSCommon);
200
201       /* Adjust the symbol value if appropriate.  */
202       switch (internal_sym.st)
203         {
204         case stNil:
205           if (ECOFF_IS_STAB (&internal_sym))
206             break;
207           /* Fall through.  */
208         case stGlobal:
209         case stStatic:
210         case stLabel:
211         case stProc:
212         case stStaticProc:
213           internal_sym.value += section_adjust[internal_sym.sc];
214           break;
215
216         default:
217           break;
218         }
219
220       (*swap_sym_out) (output_bfd, &internal_sym, sym_out);
221       sym_out += output_swap->external_sym_size;
222     }
223
224   /* Copy the information that does not need swapping.  */
225   memcpy (output_debug->line + output_symhdr->cbLine,
226           input_debug->line,
227           (size_t) (input_symhdr->cbLine * sizeof (unsigned char)));
228   memcpy (output_debug->external_aux + output_symhdr->iauxMax,
229           input_debug->external_aux,
230           (size_t) (input_symhdr->iauxMax * sizeof (union aux_ext)));
231   memcpy (output_debug->ss + output_symhdr->issMax,
232           input_debug->ss,
233           (size_t) (input_symhdr->issMax * sizeof (char)));
234
235   /* Some of the information may need to be swapped.  */
236   if (output_bfd->xvec->header_byteorder_big_p
237       == input_bfd->xvec->header_byteorder_big_p)
238     {
239       /* The two BFD's have the same endianness, so memcpy will
240          suffice.  */
241 #if 0
242       /* I don't think dense number information is needed.  */
243       BFD_ASSERT (output_swap->external_dnr_size
244                   == input_swap->external_dnr_size);
245       if (input_symhdr->idnMax > 0)
246         memcpy (((char *) output_debug->external_dnr
247                  + output_symhdr->idnMax * output_swap->external_dnr_size),
248                 input_debug->external_dnr,
249                 ((size_t)
250                  (input_symhdr->idnMax * output_swap->external_dnr_size)));
251 #endif
252       BFD_ASSERT (output_swap->external_pdr_size
253                   == input_swap->external_pdr_size);
254       if (input_symhdr->ipdMax > 0)
255         memcpy (((char *) output_debug->external_pdr
256                  + output_symhdr->ipdMax * output_swap->external_pdr_size),
257                 input_debug->external_pdr,
258                 ((size_t)
259                  (input_symhdr->ipdMax * output_swap->external_pdr_size)));
260       BFD_ASSERT (output_swap->external_opt_size
261                   == input_swap->external_opt_size);
262       if (input_symhdr->ioptMax > 0)
263         memcpy (((char *) output_debug->external_opt
264                  + output_symhdr->ioptMax * output_swap->external_opt_size),
265                 input_debug->external_opt,
266                 ((size_t)
267                  (input_symhdr->ioptMax * output_swap->external_opt_size)));
268     }
269   else
270     {
271       bfd_size_type outsz, insz;
272       char *in;
273       char *end;
274       char *out;
275
276       /* The two BFD's have different endianness, so we must swap
277          everything in and out.  This code would always work, but it
278          would be slow in the normal case.  */
279 #if 0
280       /* I don't think dense number information is needed.  */
281       outsz = output_swap->external_dnr_size;
282       insz = input_swap->external_dnr_size;
283       in = (char *) input_debug->external_dnr;
284       end = in + input_symhdr->idnMax * insz;
285       out = ((char *) output_debug->external_dnr
286              + output_symhdr->idnMax * outsz);
287       for (; in < end; in += insz, out += outsz)
288         {
289           DNR dnr;
290
291           (*input_swap->swap_dnr_in) (input_bfd, in, &dnr);
292           (*output_swap->swap_dnr_out) (output_bfd, &dnr, out);
293         }
294 #endif
295
296       outsz = output_swap->external_pdr_size;
297       insz = input_swap->external_pdr_size;
298       in = (char *) input_debug->external_pdr;
299       end = in + input_symhdr->ipdMax * insz;
300       out = ((char *) output_debug->external_pdr
301              + output_symhdr->ipdMax * outsz);
302       for (; in < end; in += insz, out += outsz)
303         {
304           PDR pdr;
305
306           (*input_swap->swap_pdr_in) (input_bfd, in, &pdr);
307           (*output_swap->swap_pdr_out) (output_bfd, &pdr, out);
308         }
309
310       outsz = output_swap->external_opt_size;
311       insz = input_swap->external_opt_size;
312       in = (char *) input_debug->external_opt;
313       end = in + input_symhdr->ioptMax * insz;
314       out = ((char *) output_debug->external_opt
315              + output_symhdr->ioptMax * outsz);
316       for (; in < end; in += insz, out += outsz)
317         {
318           OPTR opt;
319
320           (*input_swap->swap_opt_in) (input_bfd, in, &opt);
321           (*output_swap->swap_opt_out) (output_bfd, &opt, out);
322         }
323     }
324
325   /* Set ifdbase so that the external symbols know how to adjust their
326      ifd values.  */
327   input_debug->ifdbase = output_symhdr->ifdMax;
328
329   /* We need to handle the FDR's whether they are swapped or not.  */
330   if (input_debug->fdr != (FDR *) NULL)
331     {
332       fdr_ptr = (char *) input_debug->fdr;
333       fdr_add = sizeof (FDR);
334     }
335   else
336     {
337       fdr_ptr = (char *) input_debug->external_fdr;
338       fdr_add = input_swap->external_fdr_size;
339     }
340   fdr_end = fdr_ptr + input_symhdr->ifdMax * fdr_add;
341   fdr_out = ((char *) output_debug->external_fdr
342              + output_symhdr->ifdMax * output_swap->external_fdr_size);
343   for (;
344        fdr_ptr < fdr_end;
345        fdr_ptr += fdr_add, fdr_out += output_swap->external_fdr_size)
346     {
347       FDR fdr;
348
349       if (input_debug->fdr != (FDR *) NULL)
350         fdr = *(FDR *) fdr_ptr;
351       else
352         (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
353
354       /* FIXME: It is conceivable that this FDR points to the .init or
355          .fini section, in which case this will not do the right
356          thing.  */
357       fdr.adr += section_adjust[scText];
358
359       fdr.issBase += output_symhdr->issMax;
360       fdr.isymBase += output_symhdr->isymMax;
361       fdr.ilineBase += output_symhdr->ilineMax;
362       fdr.ioptBase += output_symhdr->ioptMax;
363       fdr.ipdFirst += output_symhdr->ipdMax;
364       fdr.iauxBase += output_symhdr->iauxMax;
365       fdr.rfdBase += output_symhdr->crfd;
366
367       /* If there are no RFD's, we are going to add some.  We don't
368          want to adjust crfd for this, so that all the FDR's can share
369          the RFD's.  */
370       if (input_symhdr->crfd == 0)
371         fdr.crfd = input_symhdr->ifdMax;
372
373       if (fdr.cbLine != 0)
374         fdr.cbLineOffset += output_symhdr->cbLine;
375
376       (*swap_fdr_out) (output_bfd, &fdr, fdr_out);
377     }
378
379   if (input_symhdr->crfd > 0)
380     {
381       void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
382         = input_swap->swap_rfd_in;
383       bfd_size_type outsz, insz;
384       char *rfd_in;
385       char *rfd_end;
386       char *rfd_out;
387
388       /* Swap and adjust the RFD's.  RFD's are only created by the
389          linker, so this will only be necessary if one of the input
390          files is the result of a partial link.  Presumably all
391          necessary RFD's are present.  */
392       outsz = output_swap->external_rfd_size;
393       insz = input_swap->external_rfd_size;
394       rfd_in = (char *) input_debug->external_rfd;
395       rfd_end = rfd_in + input_symhdr->crfd * insz;
396       rfd_out = ((char *) output_debug->external_rfd
397                  + output_symhdr->crfd * outsz);
398       for (;
399            rfd_in < rfd_end;
400            rfd_in += insz, rfd_out += outsz)
401         {
402           RFDT rfd;
403
404           (*swap_rfd_in) (input_bfd, rfd_in, &rfd);
405           rfd += output_symhdr->ifdMax;
406           (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
407         }
408       output_symhdr->crfd += input_symhdr->crfd;
409     }
410   else
411     {
412       bfd_size_type outsz;
413       char *rfd_out;
414       char *rfd_end;
415       RFDT rfd;
416
417       /* Create RFD's.  Some of the debugging information includes
418          relative file indices.  These indices are taken as indices to
419          the RFD table if there is one, or to the global table if
420          there is not.  If we did not create RFD's, we would have to
421          parse and adjust all the debugging information which contains
422          file indices.  */
423       outsz = output_swap->external_rfd_size;
424       rfd = output_symhdr->ifdMax;
425       rfd_out = ((char *) output_debug->external_rfd
426                  + output_symhdr->crfd * outsz);
427       rfd_end = (rfd_out + input_symhdr->ifdMax * outsz);
428       for (; rfd_out < rfd_end; rfd_out += outsz, rfd++)
429         (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
430       output_symhdr->crfd += input_symhdr->ifdMax;
431     }
432
433   /* Update the counts.  */
434   output_symhdr->ilineMax += input_symhdr->ilineMax;
435   output_symhdr->cbLine += input_symhdr->cbLine;
436 #if 0
437   /* I don't think dense number information is needed.  */
438   output_symhdr->idnMax += input_symhdr->idnMax;
439 #endif
440   output_symhdr->ipdMax += input_symhdr->ipdMax;
441   output_symhdr->isymMax += input_symhdr->isymMax;
442   output_symhdr->ioptMax += input_symhdr->ioptMax;
443   output_symhdr->iauxMax += input_symhdr->iauxMax;
444   output_symhdr->issMax += input_symhdr->issMax;
445   output_symhdr->ifdMax += input_symhdr->ifdMax;
446
447   return true;
448 }
449
450 /* Add a string to the debugging information we are accumulating.
451    Return the offset from the fdr string base.  */
452
453 static bfd_size_type
454 ecoff_add_string (output, fdr, string)
455      struct ecoff_debug_info *output;
456      FDR *fdr;
457      const char *string;
458 {
459   HDRR *symhdr;
460   size_t len;
461   bfd_size_type ret;
462
463   symhdr = &output->symbolic_header;
464   len = strlen (string);
465   if (output->ss_end - output->ss < symhdr->issMax + len + 1)
466     {
467       if (ecoff_add_bytes (&output->ss, &output->ss_end,
468                            symhdr->issMax + len + 1) == false)
469         return (bfd_size_type) -1;
470     }
471   memcpy (output->ss + symhdr->issMax, string, len + 1);
472   ret = fdr->cbSs;
473   symhdr->issMax += len + 1;
474   fdr->cbSs += len + 1;
475   return ret;
476 }
477
478 /* Add debugging information from a non-ECOFF file.  */
479
480 boolean
481 bfd_ecoff_debug_link_other (output_bfd, output_debug, output_swap, input_bfd)
482      bfd *output_bfd;
483      struct ecoff_debug_info *output_debug;
484      const struct ecoff_debug_swap *output_swap;
485      bfd *input_bfd;
486 {
487   void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
488     = output_swap->swap_sym_out;
489   HDRR *output_symhdr = &output_debug->symbolic_header;
490   FDR fdr;
491   asection *sec;
492   asymbol **symbols;
493   asymbol **sym_ptr;
494   asymbol **sym_end;
495
496   memset (&fdr, 0, sizeof fdr);
497
498   sec = bfd_get_section_by_name (input_bfd, ".text");
499   if (sec != NULL)
500     fdr.adr = sec->output_section->vma + sec->output_offset;
501   else
502     {
503       /* FIXME: What about .init or .fini?  */
504       fdr.adr = 0;
505     }
506
507   fdr.issBase = output_symhdr->issMax;
508   fdr.cbSs = 0;
509   fdr.rss = ecoff_add_string (output_debug, &fdr,
510                               bfd_get_filename (input_bfd));
511   if (fdr.rss == -1)
512     return false;
513   fdr.isymBase = output_symhdr->isymMax;
514
515   /* Get the local symbols from the input BFD.  */
516   symbols = (asymbol **) bfd_alloc (output_bfd,
517                                     get_symtab_upper_bound (input_bfd));
518   if (symbols == (asymbol **) NULL)
519     {
520       bfd_error = no_memory;
521       return false;
522     }
523   sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
524
525   /* Handle the local symbols.  Any external symbols are handled
526      separately.  */
527   fdr.csym = 0;
528   for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++)
529     {
530       SYMR internal_sym;
531
532       if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
533         continue;
534       memset (&internal_sym, 0, sizeof internal_sym);
535       internal_sym.iss = ecoff_add_string (output_debug, &fdr,
536                                            (*sym_ptr)->name);
537
538       if (internal_sym.iss == -1)
539         return false;
540       if (bfd_is_com_section ((*sym_ptr)->section)
541           || (*sym_ptr)->section == &bfd_und_section)
542         internal_sym.value = (*sym_ptr)->value;
543       else
544         internal_sym.value = ((*sym_ptr)->value
545                               + (*sym_ptr)->section->output_offset
546                               + (*sym_ptr)->section->output_section->vma);
547       internal_sym.st = stNil;
548       internal_sym.sc = scUndefined;
549       internal_sym.index = indexNil;
550
551       if (((char *) output_debug->external_sym_end
552            - (char *) output_debug->external_sym)
553           < (output_symhdr->isymMax + 1) * output_swap->external_sym_size)
554         {
555           if (! ecoff_add_bytes ((char **) &output_debug->external_sym,
556                                  (char **) &output_debug->external_sym_end,
557                                  ((output_symhdr->isymMax + 1)
558                                   * output_swap->external_sym_size)))
559             return false;
560         }
561
562       (*swap_sym_out) (output_bfd, &internal_sym,
563                        ((char *) output_debug->external_sym
564                         + (output_symhdr->isymMax
565                            * output_swap->external_sym_size)));
566       ++fdr.csym;
567       ++output_symhdr->isymMax;
568     }
569
570   bfd_release (output_bfd, (PTR) symbols);
571
572   if (((char *) output_debug->external_fdr_end
573        - (char *) output_debug->external_fdr)
574       < (output_symhdr->ifdMax + 1) * output_swap->external_fdr_size)
575     {
576       if (! ecoff_add_bytes ((char **) &output_debug->external_fdr,
577                              (char **) &output_debug->external_fdr_end,
578                              ((output_symhdr->ifdMax + 1)
579                               * output_swap->external_fdr_size)))
580         return false;
581     }
582
583   /* Leave everything else in the FDR zeroed out.  This will cause
584      the lang field to be langC.  The fBigendian field will
585      indicate little endian format, but it doesn't matter because
586      it only applies to aux fields and there are none.  */
587   (*output_swap->swap_fdr_out)
588     (output_bfd, &fdr,
589      ((char *) output_debug->external_fdr
590       + output_symhdr->ifdMax * output_swap->external_fdr_size));
591   ++output_symhdr->ifdMax;
592   return true;
593 }
594
595 /* Set up ECOFF debugging information for the external symbols.  */
596
597 boolean
598 bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr,
599                            set_index)
600      bfd *abfd;
601      struct ecoff_debug_info *debug;
602      const struct ecoff_debug_swap *swap;
603      boolean relocateable;
604      boolean (*get_extr) PARAMS ((asymbol *, EXTR *));
605      void (*set_index) PARAMS ((asymbol *, bfd_size_type));
606 {
607   HDRR * const symhdr = &debug->symbolic_header;
608   asymbol **sym_ptr_ptr;
609   size_t c;
610
611   sym_ptr_ptr = bfd_get_outsymbols (abfd);
612   if (sym_ptr_ptr == NULL)
613     return true;
614
615   for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++)
616     {
617       asymbol *sym_ptr;
618       EXTR esym;
619
620       sym_ptr = *sym_ptr_ptr;
621
622       /* Get the external symbol information.  */
623       if ((*get_extr) (sym_ptr, &esym) == false)
624         continue;
625
626       /* If we're producing an executable, move common symbols into
627          bss.  */
628       if (relocateable == false)
629         {
630           if (esym.asym.sc == scCommon)
631             esym.asym.sc = scBss;
632           else if (esym.asym.sc == scSCommon)
633             esym.asym.sc = scSBss;
634         }
635
636
637       if (bfd_is_com_section (sym_ptr->section)
638           || sym_ptr->section == &bfd_und_section)
639         esym.asym.value = sym_ptr->value;
640       else
641         esym.asym.value = (sym_ptr->value
642                            + sym_ptr->section->output_offset
643                            + sym_ptr->section->output_section->vma);
644
645       if (set_index)
646         (*set_index) (sym_ptr, (bfd_size_type) symhdr->iextMax);
647
648       if (! bfd_ecoff_debug_one_external (abfd, debug, swap,
649                                           sym_ptr->name, &esym))
650         return false;
651     }
652
653   return true;
654 }
655
656 /* Add a single external symbol to the debugging information.  */
657
658 boolean
659 bfd_ecoff_debug_one_external (abfd, debug, swap, name, esym)
660      bfd *abfd;
661      struct ecoff_debug_info *debug;
662      const struct ecoff_debug_swap *swap;
663      const char *name;
664      EXTR *esym;
665 {
666   const bfd_size_type external_ext_size = swap->external_ext_size;
667   void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR))
668     = swap->swap_ext_out;
669   HDRR * const symhdr = &debug->symbolic_header;
670   size_t namelen;
671
672   namelen = strlen (name);
673
674   if (debug->ssext_end - debug->ssext
675       < symhdr->issExtMax + namelen + 1)
676     {
677       if (ecoff_add_bytes ((char **) &debug->ssext,
678                            (char **) &debug->ssext_end,
679                            symhdr->issExtMax + namelen + 1)
680           == false)
681         return false;
682     }
683   if ((char *) debug->external_ext_end - (char *) debug->external_ext
684       < (symhdr->iextMax + 1) * external_ext_size)
685     {
686       if (ecoff_add_bytes ((char **) &debug->external_ext,
687                            (char **) &debug->external_ext_end,
688                            (symhdr->iextMax + 1) * external_ext_size)
689           == false)
690         return false;
691     }
692
693   esym->asym.iss = symhdr->issExtMax;
694
695   (*swap_ext_out) (abfd, esym,
696                    ((char *) debug->external_ext
697                     + symhdr->iextMax * swap->external_ext_size));
698
699   ++symhdr->iextMax;
700
701   strcpy (debug->ssext + symhdr->issExtMax, name);
702   symhdr->issExtMax += namelen + 1;
703
704   return true;
705 }
706
707 /* Align the ECOFF debugging information.  */
708
709 /*ARGSUSED*/
710 static void
711 ecoff_align_debug (abfd, debug, swap)
712      bfd *abfd;
713      struct ecoff_debug_info *debug;
714      const struct ecoff_debug_swap *swap;
715 {
716   HDRR * const symhdr = &debug->symbolic_header;
717   bfd_size_type debug_align, aux_align;
718   size_t add;
719
720   /* Adjust the counts so that structures are aligned.  The alignment
721      of ALLOC_SIZE ensures that we do not have to worry about running
722      off the end of the memory block when doing the memset.  */
723   debug_align = swap->debug_align;
724   aux_align = debug_align / sizeof (union aux_ext);
725
726   add = debug_align - (symhdr->cbLine & (debug_align - 1));
727   if (add != debug_align)
728     {
729       memset (debug->line + symhdr->cbLine, 0, add);
730       symhdr->cbLine += add;
731     }
732
733   add = debug_align - (symhdr->issMax & (debug_align - 1));
734   if (add != debug_align)
735     {
736       memset (debug->ss + symhdr->issMax, 0, add);
737       symhdr->issMax += add;
738     }
739
740   add = debug_align - (symhdr->issExtMax & (debug_align - 1));
741   if (add != debug_align)
742     {
743       memset (debug->ssext + symhdr->issExtMax, 0, add);
744       symhdr->issExtMax += add;
745     }
746
747   add = aux_align - (symhdr->iauxMax & (aux_align - 1));
748   if (add != aux_align)
749     {
750       memset (debug->external_aux + symhdr->iauxMax, 0,
751               add * sizeof (union aux_ext));
752       symhdr->iauxMax += add;
753     }
754 }
755
756 /* Return the size required by the ECOFF debugging information.  */
757
758 bfd_size_type
759 bfd_ecoff_debug_size (abfd, debug, swap)
760      bfd *abfd;
761      struct ecoff_debug_info *debug;
762      const struct ecoff_debug_swap *swap;
763 {
764   bfd_size_type tot;
765
766   ecoff_align_debug (abfd, debug, swap);
767   tot = swap->external_hdr_size;
768
769 #define ADD(count, size) \
770   tot += debug->symbolic_header.count * size
771
772   ADD (cbLine, sizeof (unsigned char));
773   ADD (idnMax, swap->external_dnr_size);
774   ADD (ipdMax, swap->external_pdr_size);
775   ADD (isymMax, swap->external_sym_size);
776   ADD (ioptMax, swap->external_opt_size);
777   ADD (iauxMax, sizeof (union aux_ext));
778   ADD (issMax, sizeof (char));
779   ADD (issExtMax, sizeof (char));
780   ADD (ifdMax, swap->external_fdr_size);
781   ADD (crfd, swap->external_rfd_size);
782   ADD (iextMax, swap->external_ext_size);
783
784 #undef ADD
785
786   return tot;
787 }
788
789 /* Write out the ECOFF debugging information.  This function assumes
790    that the information (the pointers and counts) in *DEBUG have been
791    set correctly.  WHERE is the position in the file to write the
792    information to.  This function fills in the file offsets in the
793    symbolic header.  */
794
795 boolean
796 bfd_ecoff_write_debug (abfd, debug, swap, where)
797      bfd *abfd;
798      struct ecoff_debug_info *debug;
799      const struct ecoff_debug_swap *swap;
800      file_ptr where;
801 {
802   HDRR * const symhdr = &debug->symbolic_header;
803   char *buff;
804
805   ecoff_align_debug (abfd, debug, swap);
806
807   /* Go to the right location in the file.  */
808   if (bfd_seek (abfd, where, SEEK_SET) != 0)
809     return false;
810
811   where += swap->external_hdr_size;
812
813   /* Fill in the file offsets.  */
814 #define SET(offset, count, size) \
815   if (symhdr->count == 0) \
816     symhdr->offset = 0; \
817   else \
818     { \
819       symhdr->offset = where; \
820       where += symhdr->count * size; \
821     }
822
823   SET (cbLineOffset, cbLine, sizeof (unsigned char));
824   SET (cbDnOffset, idnMax, swap->external_dnr_size);
825   SET (cbPdOffset, ipdMax, swap->external_pdr_size);
826   SET (cbSymOffset, isymMax, swap->external_sym_size);
827   SET (cbOptOffset, ioptMax, swap->external_opt_size);
828   SET (cbAuxOffset, iauxMax, sizeof (union aux_ext));
829   SET (cbSsOffset, issMax, sizeof (char));
830   SET (cbSsExtOffset, issExtMax, sizeof (char));
831   SET (cbFdOffset, ifdMax, swap->external_fdr_size);
832   SET (cbRfdOffset, crfd, swap->external_rfd_size);
833   SET (cbExtOffset, iextMax, swap->external_ext_size);
834 #undef SET
835
836   buff = (PTR) alloca (swap->external_hdr_size);
837   (*swap->swap_hdr_out) (abfd, symhdr, buff);
838   if (bfd_write (buff, 1, swap->external_hdr_size, abfd)
839       != swap->external_hdr_size)
840     return false;
841
842 #define WRITE(ptr, count, size, offset) \
843   BFD_ASSERT (symhdr->offset == 0 || bfd_tell (abfd) == symhdr->offset); \
844   if (bfd_write ((PTR) debug->ptr, size, symhdr->count, abfd) \
845       != size * symhdr->count) \
846     return false;
847
848   WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset);
849   WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset);
850   WRITE (external_pdr, ipdMax, swap->external_pdr_size, cbPdOffset);
851   WRITE (external_sym, isymMax, swap->external_sym_size, cbSymOffset);
852   WRITE (external_opt, ioptMax, swap->external_opt_size, cbOptOffset);
853   WRITE (external_aux, iauxMax, sizeof (union aux_ext), cbAuxOffset);
854   WRITE (ss, issMax, sizeof (char), cbSsOffset);
855   WRITE (ssext, issExtMax, sizeof (char), cbSsExtOffset);
856   WRITE (external_fdr, ifdMax, swap->external_fdr_size, cbFdOffset);
857   WRITE (external_rfd, crfd, swap->external_rfd_size, cbRfdOffset);
858   WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset);
859 #undef WRITE
860
861   return true;
862 }