ac9de9f86fd0892c1d7475265b60f7f1d69bcbab
[deliverable/binutils-gdb.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 }
This page took 0.046328 seconds and 3 git commands to generate.