New file to hold ECOFF linking routines used by both ECOFF and MIPS ELF.
[deliverable/binutils-gdb.git] / bfd / ecofflink.c
CommitLineData
71efdf83
ILT
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
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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
29static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend,
30 bfd_size_type need));
31static bfd_size_type ecoff_add_string PARAMS ((struct ecoff_debug_info *,
32 FDR *fdr, const char *string));
33static 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
42static boolean
43ecoff_add_bytes (buf, bufend, need)
44 char **buf;
45 char **bufend;
46 bfd_size_type need;
47{
48 bfd_size_type have;
49 bfd_size_type 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
81boolean
82bfd_ecoff_debug_accumulate (output_bfd, output_debug, output_swap,
83 input_bfd, input_debug, input_swap,
84 relocateable)
85 bfd *output_bfd;
86 struct ecoff_debug_info *output_debug;
87 const struct ecoff_debug_swap *output_swap;
88 bfd *input_bfd;
89 struct ecoff_debug_info *input_debug;
90 const struct ecoff_debug_swap *input_swap;
91 boolean relocateable;
92{
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;
101 HDRR *output_symhdr;
102 HDRR *input_symhdr;
103 bfd_vma section_adjust[scMax];
104 asection *sec;
105 char *sym_out;
106 char *lraw_src;
107 char *lraw_end;
108 char *fdr_ptr;
109 char *fdr_end;
110 bfd_size_type fdr_add;
111 char *fdr_out;
112
113 output_symhdr = &output_debug->symbolic_header;
114 input_symhdr = &input_debug->symbolic_header;
115
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) \
120 { \
121 if (! ecoff_add_bytes ((char **) &output_debug->start, \
122 (char **) &output_debug->end, \
123 ((output_symhdr->count \
124 + input_symhdr->count) \
125 * size))) \
126 return false; \
127 }
128
129 CHECK (line, line_end, cbLine, sizeof (unsigned char));
130#if 0
131 /* I don't think dense number information is needed. */
132 CHECK (external_dnr, external_dnr_end, idnMax,
133 output_swap->external_dnr_size);
134#endif
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);
146
147 /* The RFD's are special, since we create them if needed. */
148 {
149 bfd_size_type crfd;
150
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;
157 }
158
159#undef CHECK
160
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);
164
165#define SET(name, indx) \
166 sec = bfd_get_section_by_name (input_bfd, name); \
167 if (sec != NULL) \
168 section_adjust[indx] = (sec->output_section->vma \
169 + sec->output_offset \
170 - sec->vma);
171
172 SET (".text", scText);
173 SET (".data", scData);
174 SET (".bss", scBss);
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);
182
183#undef SET
184
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)
192 {
193 SYMR internal_sym;
194
195 (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym);
196
197 BFD_ASSERT (internal_sym.sc != scCommon
198 && internal_sym.sc != scSCommon);
199
200 /* Adjust the symbol value if appropriate. */
201 switch (internal_sym.st)
202 {
203 case stNil:
204 if (ECOFF_IS_STAB (&internal_sym))
205 break;
206 /* Fall through. */
207 case stGlobal:
208 case stStatic:
209 case stLabel:
210 case stProc:
211 case stStaticProc:
212 internal_sym.value += section_adjust[internal_sym.sc];
213 break;
214
215 default:
216 break;
217 }
218
219 (*swap_sym_out) (output_bfd, &internal_sym, sym_out);
220 sym_out += output_swap->external_sym_size;
221 }
222
223 /* Copy the information that does not need swapping. */
224 memcpy (output_debug->line + output_symhdr->cbLine,
225 input_debug->line,
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,
231 input_debug->ss,
232 input_symhdr->issMax * sizeof (char));
233
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)
237 {
238 /* The two BFD's have the same endianness, so memcpy will
239 suffice. */
240#if 0
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);
249#endif
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);
264 }
265 else
266 {
267 bfd_size_type outsz, insz;
268 char *in;
269 char *end;
270 char *out;
271
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. */
275#if 0
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)
284 {
285 DNR dnr;
286
287 (*input_swap->swap_dnr_in) (input_bfd, in, &dnr);
288 (*output_swap->swap_dnr_out) (output_bfd, &dnr, out);
289 }
290#endif
291
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)
299 {
300 PDR pdr;
301
302 (*input_swap->swap_pdr_in) (input_bfd, in, &pdr);
303 (*output_swap->swap_pdr_out) (output_bfd, &pdr, out);
304 }
305
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)
313 {
314 OPTR opt;
315
316 (*input_swap->swap_opt_in) (input_bfd, in, &opt);
317 (*output_swap->swap_opt_out) (output_bfd, &opt, out);
318 }
319 }
320
321 /* Set ifdbase so that the external symbols know how to adjust their
322 ifd values. */
323 input_debug->ifdbase = output_symhdr->ifdMax;
324
325 /* We need to handle the FDR's whether they are swapped or not. */
326 if (input_debug->fdr != (FDR *) NULL)
327 {
328 fdr_ptr = (char *) input_debug->fdr;
329 fdr_add = sizeof (FDR);
330 }
331 else
332 {
333 fdr_ptr = (char *) input_debug->external_fdr;
334 fdr_add = input_swap->external_fdr_size;
335 }
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);
339 for (;
340 fdr_ptr < fdr_end;
341 fdr_ptr += fdr_add, fdr_out += output_swap->external_fdr_size)
342 {
343 FDR fdr;
344
345 if (input_debug->fdr != (FDR *) NULL)
346 fdr = *(FDR *) fdr_ptr;
347 else
348 (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
349
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
352 thing. */
353 fdr.adr += section_adjust[scText];
354
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;
362
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
365 the RFD's. */
366 if (input_symhdr->crfd == 0)
367 fdr.crfd = input_symhdr->ifdMax;
368
369 if (fdr.cbLine != 0)
370 fdr.cbLineOffset += output_symhdr->cbLine;
371
372 (*swap_fdr_out) (output_bfd, &fdr, fdr_out);
373 }
374
375 if (input_symhdr->crfd > 0)
376 {
377 void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
378 = input_swap->swap_rfd_in;
379 bfd_size_type outsz, insz;
380 char *rfd_in;
381 char *rfd_end;
382 char *rfd_out;
383
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);
394 for (;
395 rfd_in < rfd_end;
396 rfd_in += insz, rfd_out += outsz)
397 {
398 RFDT rfd;
399
400 (*swap_rfd_in) (input_bfd, rfd_in, &rfd);
401 rfd += output_symhdr->ifdMax;
402 (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
403 }
404 output_symhdr->crfd += input_symhdr->crfd;
405 }
406 else
407 {
408 bfd_size_type outsz;
409 char *rfd_out;
410 char *rfd_end;
411 RFDT rfd;
412
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
418 file indices. */
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;
427 }
428
429 /* Update the counts. */
430 output_symhdr->ilineMax += input_symhdr->ilineMax;
431 output_symhdr->cbLine += input_symhdr->cbLine;
432#if 0
433 /* I don't think dense number information is needed. */
434 output_symhdr->idnMax += input_symhdr->idnMax;
435#endif
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;
442
443 return true;
444}
445
446/* Add a string to the debugging information we are accumulating.
447 Return the offset from the fdr string base. */
448
449static bfd_size_type
450ecoff_add_string (output, fdr, string)
451 struct ecoff_debug_info *output;
452 FDR *fdr;
453 const char *string;
454{
455 HDRR *symhdr;
456 size_t len;
457 bfd_size_type ret;
458
459 symhdr = &output->symbolic_header;
460 len = strlen (string);
461 if (output->ss_end - output->ss < symhdr->issMax + len + 1)
462 {
463 if (ecoff_add_bytes (&output->ss, &output->ss_end,
464 symhdr->issMax + len + 1) == false)
465 return -1;
466 }
467 memcpy (output->ss + symhdr->issMax, string, len + 1);
468 ret = fdr->cbSs;
469 symhdr->issMax += len + 1;
470 fdr->cbSs += len + 1;
471 return ret;
472}
473
474/* Add debugging information from a non-ECOFF file. */
475
476boolean
477bfd_ecoff_debug_link_other (output_bfd, output_debug, output_swap, input_bfd)
478 bfd *output_bfd;
479 struct ecoff_debug_info *output_debug;
480 const struct ecoff_debug_swap *output_swap;
481 bfd *input_bfd;
482{
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;
486 FDR fdr;
487 asection *sec;
488 asymbol **symbols;
489 asymbol **sym_ptr;
490 asymbol **sym_end;
491
492 memset (&fdr, 0, sizeof fdr);
493
494 sec = bfd_get_section_by_name (input_bfd, ".text");
495 if (sec != NULL)
496 fdr.adr = sec->output_section->vma + sec->output_offset;
497 else
498 {
499 /* FIXME: What about .init or .fini? */
500 fdr.adr = 0;
501 }
502
503 fdr.issBase = output_symhdr->issMax;
504 fdr.cbSs = 0;
505 fdr.rss = ecoff_add_string (output_debug, &fdr,
506 bfd_get_filename (input_bfd));
507 fdr.isymBase = output_symhdr->isymMax;
508
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)
513 {
514 bfd_error = no_memory;
515 return false;
516 }
517 sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
518
519 /* Handle the local symbols. Any external symbols are handled
520 separately. */
521 fdr.csym = 0;
522 for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++)
523 {
524 SYMR internal_sym;
525
526 if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
527 continue;
528 memset (&internal_sym, 0, sizeof internal_sym);
529 internal_sym.iss = ecoff_add_string (output_debug, &fdr,
530 (*sym_ptr)->name);
531
532 if (bfd_is_com_section ((*sym_ptr)->section)
533 || (*sym_ptr)->section == &bfd_und_section)
534 internal_sym.value = (*sym_ptr)->value;
535 else
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;
542
543 if (((char *) output_debug->external_sym_end
544 - (char *) output_debug->external_sym)
545 < (output_symhdr->isymMax + 1) * output_swap->external_sym_size)
546 {
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)))
551 return false;
552 }
553
554 (*swap_sym_out) (output_bfd, &internal_sym,
555 ((char *) output_debug->external_sym
556 + (output_symhdr->isymMax
557 * output_swap->external_sym_size)));
558 ++fdr.csym;
559 ++output_symhdr->isymMax;
560 }
561
562 bfd_release (output_bfd, (PTR) symbols);
563
564 if (((char *) output_debug->external_fdr_end
565 - (char *) output_debug->external_fdr)
566 < (output_symhdr->ifdMax + 1) * output_swap->external_fdr_size)
567 {
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)))
572 return false;
573 }
574
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)
580 (output_bfd, &fdr,
581 ((char *) output_debug->external_fdr
582 + output_symhdr->ifdMax * output_swap->external_fdr_size));
583 ++output_symhdr->ifdMax;
584 return true;
585}
586
587/* Set up ECOFF debugging information for the external symbols. */
588
589boolean
590bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr,
591 set_index)
592 bfd *abfd;
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));
598{
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;
604 size_t c;
605
606 sym_ptr_ptr = bfd_get_outsymbols (abfd);
607 if (sym_ptr_ptr == NULL)
608 return true;
609
610 for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++)
611 {
612 asymbol *sym_ptr;
613 EXTR esym;
614
615 sym_ptr = *sym_ptr_ptr;
616
617 /* Get the external symbol information. */
618 if ((*get_extr) (sym_ptr, &esym) == false)
619 continue;
620
621 /* If we're producing an executable, move common symbols into
622 bss. */
623 if (relocateable == false)
624 {
625 if (esym.asym.sc == scCommon)
626 esym.asym.sc = scBss;
627 else if (esym.asym.sc == scSCommon)
628 esym.asym.sc = scSBss;
629 }
630
631 if (debug->ssext_end - debug->ssext
632 < symhdr->issExtMax + strlen (sym_ptr->name) + 1)
633 {
634 if (ecoff_add_bytes ((char **) &debug->ssext,
635 (char **) &debug->ssext_end,
636 symhdr->issExtMax + strlen (sym_ptr->name) + 1)
637 == false)
638 return false;
639 }
640 if ((char *) debug->external_ext_end - (char *) debug->external_ext
641 < (symhdr->iextMax + 1) * external_ext_size)
642 {
643 if (ecoff_add_bytes ((char **) &debug->external_ext,
644 (char **) &debug->external_ext_end,
645 (symhdr->iextMax + 1) * external_ext_size)
646 == false)
647 return false;
648 }
649
650 esym.asym.iss = symhdr->issExtMax;
651
652 if (bfd_is_com_section (sym_ptr->section)
653 || sym_ptr->section == &bfd_und_section)
654 esym.asym.value = sym_ptr->value;
655 else
656 esym.asym.value = (sym_ptr->value
657 + sym_ptr->section->output_offset
658 + sym_ptr->section->output_section->vma);
659
660 (*swap_ext_out) (abfd, &esym,
661 ((char *) debug->external_ext
662 + symhdr->iextMax * swap->external_ext_size));
663
664 if (set_index)
665 (*set_index) (sym_ptr, symhdr->iextMax);
666
667 ++symhdr->iextMax;
668
669 strcpy (debug->ssext + symhdr->issExtMax, sym_ptr->name);
670 symhdr->issExtMax += strlen (sym_ptr->name) + 1;
671 }
672
673 return true;
674}
675
676/* Align the ECOFF debugging information. */
677
678static void
679ecoff_align_debug (abfd, debug, swap)
680 bfd *abfd;
681 struct ecoff_debug_info *debug;
682 const struct ecoff_debug_swap *swap;
683{
684 HDRR * const symhdr = &debug->symbolic_header;
685 bfd_size_type debug_align, aux_align, add;
686
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);
692
693 add = debug_align - (symhdr->cbLine & (debug_align - 1));
694 if (add != debug_align)
695 {
696 memset (debug->line + symhdr->cbLine, 0, add);
697 symhdr->cbLine += add;
698 }
699
700 add = debug_align - (symhdr->issMax & (debug_align - 1));
701 if (add != debug_align)
702 {
703 memset (debug->ss + symhdr->issMax, 0, add);
704 symhdr->issMax += add;
705 }
706
707 add = debug_align - (symhdr->issExtMax & (debug_align - 1));
708 if (add != debug_align)
709 {
710 memset (debug->ssext + symhdr->issExtMax, 0, add);
711 symhdr->issExtMax += add;
712 }
713
714 add = aux_align - (symhdr->iauxMax & (aux_align - 1));
715 if (add != aux_align)
716 {
717 memset (debug->external_aux + symhdr->iauxMax, 0,
718 add * sizeof (union aux_ext));
719 symhdr->iauxMax += add;
720 }
721}
722
723/* Return the size required by the ECOFF debugging information. */
724
725bfd_size_type
726bfd_ecoff_debug_size (abfd, debug, swap)
727 bfd *abfd;
728 struct ecoff_debug_info *debug;
729 const struct ecoff_debug_swap *swap;
730{
731 bfd_size_type tot;
732
733 ecoff_align_debug (abfd, debug, swap);
734 tot = swap->external_hdr_size;
735
736#define ADD(count, size) \
737 tot += debug->symbolic_header.count * size
738
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);
750
751#undef ADD
752
753 return tot;
754}
755
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
760 symbolic header. */
761
762boolean
763bfd_ecoff_write_debug (abfd, debug, swap, where)
764 bfd *abfd;
765 struct ecoff_debug_info *debug;
766 const struct ecoff_debug_swap *swap;
767 file_ptr where;
768{
769 HDRR * const symhdr = &debug->symbolic_header;
770 char *buff;
771
772 ecoff_align_debug (abfd, debug, swap);
773
774 /* Go to the right location in the file. */
775 if (bfd_seek (abfd, where, SEEK_SET) != 0)
776 return false;
777
778 where += swap->external_hdr_size;
779
780 /* Fill in the file offsets. */
781#define SET(offset, count, size) \
782 if (symhdr->count == 0) \
783 symhdr->offset = 0; \
784 else \
785 { \
786 symhdr->offset = where; \
787 where += symhdr->count * size; \
788 }
789
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);
801#undef SET
802
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)
807 return false;
808
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) \
813 return false;
814
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);
826#undef WRITE
827
828 return true;
829}
This page took 0.050634 seconds and 4 git commands to generate.