ab4676253ea2fb330b7c8e1a72e036babbe45163
[deliverable/binutils-gdb.git] / gas / config / obj-elf.c
1 /* ELF object file format
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2,
9 or (at your option) any later version.
10
11 GAS is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public
17 License along with GAS; see the file COPYING. If not, write
18 to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include "as.h"
21 #include "subsegs.h"
22 #include "obstack.h"
23
24 static int obj_elf_write_symbol_p PARAMS ((symbolS *sym));
25
26 static void obj_elf_line PARAMS ((int));
27 void obj_elf_version PARAMS ((int));
28 static void obj_elf_size PARAMS ((int));
29 static void obj_elf_type PARAMS ((int));
30 static void obj_elf_ident PARAMS ((int));
31 static void obj_elf_weak PARAMS ((int));
32 static void obj_elf_local PARAMS ((int));
33 static void obj_elf_common PARAMS ((int));
34 static void obj_elf_data PARAMS ((int));
35 static void obj_elf_text PARAMS ((int));
36
37 const pseudo_typeS obj_pseudo_table[] =
38 {
39 {"comm", obj_elf_common, 0},
40 {"ident", obj_elf_ident, 0},
41 {"local", obj_elf_local, 0},
42 {"previous", obj_elf_previous, 0},
43 {"section", obj_elf_section, 0},
44 {"size", obj_elf_size, 0},
45 {"type", obj_elf_type, 0},
46 {"version", obj_elf_version, 0},
47 {"weak", obj_elf_weak, 0},
48
49 /* These are used for stabs-in-elf configurations. */
50 {"line", obj_elf_line, 0},
51
52 /* These are used for dwarf. */
53 {"2byte", cons, 2},
54 {"4byte", cons, 4},
55 {"8byte", cons, 8},
56
57 /* We need to trap the section changing calls to handle .previous. */
58 {"data", obj_elf_data, 0},
59 {"text", obj_elf_text, 0},
60
61 {NULL} /* end sentinel */
62 };
63
64 #undef NO_RELOC
65 #include "aout/aout64.h"
66
67 void
68 elf_file_symbol (s)
69 char *s;
70 {
71 symbolS *sym;
72
73 sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
74 sym->sy_frag = &zero_address_frag;
75 sym->bsym->flags |= BSF_FILE;
76
77 if (symbol_rootP != sym)
78 {
79 symbol_remove (sym, &symbol_rootP, &symbol_lastP);
80 symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
81 #ifdef DEBUG
82 verify_symbol_chain (symbol_rootP, symbol_lastP);
83 #endif
84 }
85 }
86
87 static void
88 obj_elf_common (ignore)
89 int ignore;
90 {
91 char *name;
92 char c;
93 char *p;
94 int temp, size;
95 symbolS *symbolP;
96 int have_align;
97
98 name = input_line_pointer;
99 c = get_symbol_end ();
100 /* just after name is now '\0' */
101 p = input_line_pointer;
102 *p = c;
103 SKIP_WHITESPACE ();
104 if (*input_line_pointer != ',')
105 {
106 as_bad ("Expected comma after symbol-name");
107 ignore_rest_of_line ();
108 return;
109 }
110 input_line_pointer++; /* skip ',' */
111 if ((temp = get_absolute_expression ()) < 0)
112 {
113 as_bad (".COMMon length (%d.) <0! Ignored.", temp);
114 ignore_rest_of_line ();
115 return;
116 }
117 size = temp;
118 *p = 0;
119 symbolP = symbol_find_or_make (name);
120 *p = c;
121 if (S_IS_DEFINED (symbolP))
122 {
123 as_bad ("Ignoring attempt to re-define symbol");
124 ignore_rest_of_line ();
125 return;
126 }
127 if (S_GET_VALUE (symbolP) != 0)
128 {
129 if (S_GET_VALUE (symbolP) != size)
130 {
131 as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
132 S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
133 }
134 }
135 know (symbolP->sy_frag == &zero_address_frag);
136 if (*input_line_pointer != ',')
137 have_align = 0;
138 else
139 {
140 have_align = 1;
141 input_line_pointer++;
142 SKIP_WHITESPACE ();
143 }
144 if (! have_align || *input_line_pointer != '"')
145 {
146 if (! have_align)
147 temp = 0;
148 else
149 {
150 temp = get_absolute_expression ();
151 if (temp < 0)
152 {
153 temp = 0;
154 as_warn ("Common alignment negative; 0 assumed");
155 }
156 }
157 if (symbolP->local)
158 {
159 segT old_sec;
160 int old_subsec;
161 char *pfrag;
162 int align;
163
164 /* allocate_bss: */
165 old_sec = now_seg;
166 old_subsec = now_subseg;
167 align = temp;
168 record_alignment (bss_section, align);
169 subseg_set (bss_section, 0);
170 if (align)
171 frag_align (align, 0);
172 if (S_GET_SEGMENT (symbolP) == bss_section)
173 symbolP->sy_frag->fr_symbol = 0;
174 symbolP->sy_frag = frag_now;
175 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
176 (char *) 0);
177 *pfrag = 0;
178 S_SET_SEGMENT (symbolP, bss_section);
179 S_CLEAR_EXTERNAL (symbolP);
180 subseg_set (old_sec, old_subsec);
181 }
182 else
183 {
184 allocate_common:
185 S_SET_VALUE (symbolP, (valueT) size);
186 S_SET_EXTERNAL (symbolP);
187 /* should be common, but this is how gas does it for now */
188 S_SET_SEGMENT (symbolP, &bfd_und_section);
189 }
190 }
191 else
192 {
193 input_line_pointer++;
194 /* @@ Some use the dot, some don't. Can we get some consistency?? */
195 if (*input_line_pointer == '.')
196 input_line_pointer++;
197 /* @@ Some say data, some say bss. */
198 if (strncmp (input_line_pointer, "bss\"", 4)
199 && strncmp (input_line_pointer, "data\"", 5))
200 {
201 while (*--input_line_pointer != '"')
202 ;
203 input_line_pointer--;
204 goto bad_common_segment;
205 }
206 while (*input_line_pointer++ != '"')
207 ;
208 goto allocate_common;
209 }
210 demand_empty_rest_of_line ();
211 return;
212
213 {
214 bad_common_segment:
215 p = input_line_pointer;
216 while (*p && *p != '\n')
217 p++;
218 c = *p;
219 *p = '\0';
220 as_bad ("bad .common segment %s", input_line_pointer + 1);
221 *p = c;
222 input_line_pointer = p;
223 ignore_rest_of_line ();
224 return;
225 }
226 }
227
228 static void
229 obj_elf_local (ignore)
230 int ignore;
231 {
232 char *name;
233 int c;
234 symbolS *symbolP;
235
236 do
237 {
238 name = input_line_pointer;
239 c = get_symbol_end ();
240 symbolP = symbol_find_or_make (name);
241 *input_line_pointer = c;
242 SKIP_WHITESPACE ();
243 S_CLEAR_EXTERNAL (symbolP);
244 symbolP->local = 1;
245 if (c == ',')
246 {
247 input_line_pointer++;
248 SKIP_WHITESPACE ();
249 if (*input_line_pointer == '\n')
250 c = '\n';
251 }
252 }
253 while (c == ',');
254 demand_empty_rest_of_line ();
255 }
256
257 static void
258 obj_elf_weak (ignore)
259 int ignore;
260 {
261 char *name;
262 int c;
263 symbolS *symbolP;
264
265 do
266 {
267 name = input_line_pointer;
268 c = get_symbol_end ();
269 symbolP = symbol_find_or_make (name);
270 *input_line_pointer = c;
271 SKIP_WHITESPACE ();
272 S_SET_WEAK (symbolP);
273 symbolP->local = 1;
274 if (c == ',')
275 {
276 input_line_pointer++;
277 SKIP_WHITESPACE ();
278 if (*input_line_pointer == '\n')
279 c = '\n';
280 }
281 }
282 while (c == ',');
283 demand_empty_rest_of_line ();
284 }
285
286 static segT previous_section;
287 static int previous_subsection;
288
289 /* Handle the .section pseudo-op. This code supports two different
290 syntaxes.
291
292 The first is found on Solaris, and looks like
293 .section ".sec1",#alloc,#execinstr,#write
294 Here the names after '#' are the SHF_* flags to turn on for the
295 section. I'm not sure how it determines the SHT_* type (BFD
296 doesn't really give us control over the type, anyhow).
297
298 The second format is found on UnixWare, and probably most SVR4
299 machines, and looks like
300 .section .sec1,"a",@progbits
301 The quoted string may contain any combination of a, w, x, and
302 represents the SHF_* flags to turn on for the section. The string
303 beginning with '@' can be progbits or nobits. There should be
304 other possibilities, but I don't know what they are. In any case,
305 BFD doesn't really let us set the section type. */
306
307 void
308 obj_elf_section (xxx)
309 int xxx;
310 {
311 char *string;
312 int new_sec;
313 segT sec;
314 flagword flags;
315
316 /* Get name of section. */
317 SKIP_WHITESPACE ();
318 if (*input_line_pointer == '"')
319 {
320 string = demand_copy_C_string (&xxx);
321 if (string == NULL)
322 {
323 ignore_rest_of_line ();
324 return;
325 }
326 }
327 else
328 {
329 char *p = input_line_pointer;
330 char c;
331 while (0 == strchr ("\n\t,; ", *p))
332 p++;
333 if (p == input_line_pointer)
334 {
335 as_warn ("Missing section name");
336 ignore_rest_of_line ();
337 return;
338 }
339 c = *p;
340 *p = 0;
341 string = xmalloc ((unsigned long) (p - input_line_pointer + 1));
342 strcpy (string, input_line_pointer);
343 *p = c;
344 input_line_pointer = p;
345 }
346
347 /* Switch to the section, creating it if necessary. */
348 previous_section = now_seg;
349 previous_subsection = now_subseg;
350
351 new_sec = bfd_get_section_by_name (stdoutput, string) == NULL;
352 sec = subseg_new (string, 0);
353
354 /* If this section already existed, we don't bother to change the
355 flag values. */
356 if (! new_sec)
357 {
358 while (! is_end_of_line[(unsigned char) *input_line_pointer])
359 ++input_line_pointer;
360 ++input_line_pointer;
361 return;
362 }
363
364 SKIP_WHITESPACE ();
365 if (*input_line_pointer != ',')
366 {
367 /* No flags given. Guess at some useful defaults. */
368 if (strcmp (string, ".data") == 0
369 || strcmp (string, ".data1") == 0
370 || strcmp (string, ".sdata") == 0
371 || strcmp (string, ".rodata") == 0
372 || strcmp (string, ".rodata1") == 0)
373 flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA;
374 else if (strcmp (string, ".text") == 0
375 || strcmp (string, ".init") == 0
376 || strcmp (string, ".fini") == 0)
377 flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_CODE;
378 else if (strcmp (string, ".bss") == 0
379 || strcmp (string, ".sbss") == 0)
380 flags = SEC_ALLOC;
381 else
382 flags = SEC_RELOC;
383 }
384 else
385 {
386 /* Skip the comma. */
387 ++input_line_pointer;
388
389 SKIP_WHITESPACE ();
390 if (*input_line_pointer == '"')
391 {
392 /* Pick up a string with a combination of a, w, x. */
393 flags = SEC_READONLY | SEC_RELOC;
394 ++input_line_pointer;
395 while (*input_line_pointer != '"')
396 {
397 switch (*input_line_pointer)
398 {
399 case 'a':
400 flags |= SEC_ALLOC | SEC_LOAD;
401 break;
402 case 'w':
403 flags &=~ SEC_READONLY;
404 break;
405 case 'x':
406 flags |= SEC_CODE;
407 break;
408 default:
409 as_warn ("Bad .section directive: want a,w,x in string");
410 ignore_rest_of_line ();
411 return;
412 }
413 ++input_line_pointer;
414 }
415
416 /* Skip the closing quote. */
417 ++input_line_pointer;
418
419 SKIP_WHITESPACE ();
420 if (*input_line_pointer == ',')
421 {
422 ++input_line_pointer;
423 SKIP_WHITESPACE ();
424 if (*input_line_pointer == '@')
425 {
426 ++input_line_pointer;
427 if (strncmp (input_line_pointer, "progbits",
428 sizeof "progbits" - 1) == 0)
429 {
430 flags |= SEC_ALLOC | SEC_LOAD;
431 input_line_pointer += sizeof "progbits" - 1;
432 }
433 else if (strncmp (input_line_pointer, "nobits",
434 sizeof "nobits" - 1) == 0)
435 {
436 flags &=~ SEC_LOAD;
437 input_line_pointer += sizeof "nobits" - 1;
438 }
439 else
440 {
441 as_warn ("Unrecognized section type");
442 ignore_rest_of_line ();
443 }
444 }
445 }
446 }
447 else
448 {
449 flags = SEC_READONLY | SEC_RELOC;
450 do
451 {
452 SKIP_WHITESPACE ();
453 if (*input_line_pointer != '#')
454 {
455 as_warn ("Bad .section directive");
456 ignore_rest_of_line ();
457 return;
458 }
459 ++input_line_pointer;
460 if (strncmp (input_line_pointer, "write",
461 sizeof "write" - 1) == 0)
462 {
463 flags &=~ SEC_READONLY;
464 input_line_pointer += sizeof "write" - 1;
465 }
466 else if (strncmp (input_line_pointer, "alloc",
467 sizeof "alloc" - 1) == 0)
468 {
469 flags |= SEC_ALLOC | SEC_LOAD;
470 input_line_pointer += sizeof "alloc" - 1;
471 }
472 else if (strncmp (input_line_pointer, "execinstr",
473 sizeof "execinstr" - 1) == 0)
474 {
475 flags |= SEC_CODE;
476 input_line_pointer += sizeof "execinstr" - 1;
477 }
478 else
479 {
480 as_warn ("Unrecognized section attribute");
481 ignore_rest_of_line ();
482 return;
483 }
484 SKIP_WHITESPACE ();
485 }
486 while (*input_line_pointer++ == ',');
487 --input_line_pointer;
488 }
489 }
490
491 bfd_set_section_flags (stdoutput, sec, flags);
492
493 demand_empty_rest_of_line ();
494 }
495
496 /* Change to the .data section. */
497
498 static void
499 obj_elf_data (i)
500 int i;
501 {
502 previous_section = now_seg;
503 previous_subsection = now_subseg;
504 s_data (i);
505 }
506
507 /* Change to the .text section. */
508
509 static void
510 obj_elf_text (i)
511 int i;
512 {
513 previous_section = now_seg;
514 previous_subsection = now_subseg;
515 s_text (i);
516 }
517
518 void
519 obj_elf_previous (ignore)
520 int ignore;
521 {
522 if (previous_section == 0)
523 {
524 as_bad (".previous without corresponding .section; ignored");
525 return;
526 }
527 subseg_set (previous_section, previous_subsection);
528 previous_section = 0;
529 }
530
531 static int
532 obj_elf_write_symbol_p (sym)
533 symbolS *sym;
534 {
535 /* If this is a local symbol, are there any relocations for which
536 need this symbol? */
537
538 /* To find this out, we examine all relocations in all bfd sections
539 that have relocations. If there is one that references this
540 symbol, we need to keep this symbol. In this case, we return a
541 true status. In all other cases, we return a false status. */
542
543 if (S_IS_LOCAL (sym))
544 {
545 asymbol *bsym = sym->bsym;
546 bfd *abfd = bsym->the_bfd;
547 asection *bsec;
548
549 for (bsec = abfd->sections; bsec; bsec = bsec->next)
550 {
551 struct reloc_cache_entry **rlocs = bsec->orelocation;
552 int rcnt = bsec->reloc_count;
553
554 if (rlocs)
555 {
556 int i;
557
558 for (i = 0; i < rcnt; i++)
559 if (rlocs[i]->sym_ptr_ptr
560 && rlocs[i]->sym_ptr_ptr[0] == bsym)
561 return 1;
562 }
563 else
564 {
565 /* No relocations for this section. Check the seg_info
566 structure to see if there are any fixups for this
567 section. */
568 segment_info_type *seginfo = seg_info (bsec);
569 fixS *fixp;
570
571 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
572 if ((fixp->fx_addsy && fixp->fx_addsy->bsym == bsym)
573 || (fixp->fx_subsy && fixp->fx_subsy->bsym == bsym))
574 return 1;
575 }
576 }
577 }
578 return 0;
579 }
580
581 int
582 obj_elf_write_symbol (sym)
583 symbolS *sym;
584 {
585 return /* obj_elf_write_symbol_p (sym) || */ !S_IS_LOCAL (sym);
586 }
587
588 int
589 obj_elf_frob_symbol (sym, punt)
590 symbolS *sym;
591 int *punt;
592 {
593 #if 0 /* ?? The return value is ignored. Only the value of *punt is
594 relevant. */
595 return obj_elf_write_symbol_p (sym);
596 #endif
597 /* FIXME: Just return 0 until is fixed. */
598 return 0;
599 }
600
601 static void
602 obj_elf_line (ignore)
603 int ignore;
604 {
605 /* Assume delimiter is part of expression. BSD4.2 as fails with
606 delightful bug, so we are not being incompatible here. */
607 new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
608 demand_empty_rest_of_line ();
609 }
610
611 void
612 obj_read_begin_hook ()
613 {
614 }
615
616 void
617 obj_symbol_new_hook (symbolP)
618 symbolS *symbolP;
619 {
620 #if 0 /* BFD already takes care of this */
621 elf32_symbol_type *esym = (elf32_symbol_type *) symbolP;
622
623 /* There is an Elf_Internal_Sym and an Elf_External_Sym. For now,
624 just zero them out. */
625
626 bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym));
627 bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym));
628 bzero ((char *) &esym->tc_data, sizeof (esym->tc_data));
629 #endif
630 }
631
632 void
633 obj_elf_version (ignore)
634 int ignore;
635 {
636 char *name;
637 unsigned int c;
638 char ch;
639 char *p;
640 asection *seg = now_seg;
641 subsegT subseg = now_subseg;
642 Elf_Internal_Note i_note;
643 Elf_External_Note e_note;
644 asection *note_secp = (asection *) NULL;
645 int i, len;
646
647 SKIP_WHITESPACE ();
648 if (*input_line_pointer == '\"')
649 {
650 ++input_line_pointer; /* -> 1st char of string. */
651 name = input_line_pointer;
652
653 while (is_a_char (c = next_char_of_string ()))
654 ;
655 c = *input_line_pointer;
656 *input_line_pointer = '\0';
657 *(input_line_pointer - 1) = '\0';
658 *input_line_pointer = c;
659
660 /* create the .note section */
661
662 note_secp = subseg_new (".note", 0);
663 bfd_set_section_flags (stdoutput,
664 note_secp,
665 SEC_HAS_CONTENTS | SEC_READONLY);
666
667 /* process the version string */
668
669 len = strlen (name);
670
671 i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
672 i_note.descsz = 0; /* no description */
673 i_note.type = NT_VERSION;
674 p = frag_more (sizeof (e_note.namesz));
675 md_number_to_chars (p, (valueT) i_note.namesz, 4);
676 p = frag_more (sizeof (e_note.descsz));
677 md_number_to_chars (p, (valueT) i_note.descsz, 4);
678 p = frag_more (sizeof (e_note.type));
679 md_number_to_chars (p, (valueT) i_note.type, 4);
680
681 for (i = 0; i < len; i++)
682 {
683 ch = *(name + i);
684 {
685 FRAG_APPEND_1_CHAR (ch);
686 }
687 }
688 frag_align (2, 0);
689
690 subseg_set (seg, subseg);
691 }
692 else
693 {
694 as_bad ("Expected quoted string");
695 }
696 demand_empty_rest_of_line ();
697 }
698
699 static void
700 obj_elf_size (ignore)
701 int ignore;
702 {
703 char *name = input_line_pointer;
704 char c = get_symbol_end ();
705 char *p;
706 expressionS exp;
707 symbolS *sym;
708
709 p = input_line_pointer;
710 *p = c;
711 SKIP_WHITESPACE ();
712 if (*input_line_pointer != ',')
713 {
714 *p = 0;
715 as_bad ("expected comma after name `%s' in .size directive", name);
716 *p = c;
717 ignore_rest_of_line ();
718 return;
719 }
720 input_line_pointer++;
721 expression (&exp);
722 if (exp.X_op == O_absent)
723 {
724 as_bad ("missing expression in .size directive");
725 exp.X_op = O_constant;
726 exp.X_add_number = 0;
727 }
728 *p = 0;
729 sym = symbol_find_or_make (name);
730 *p = c;
731 if (exp.X_op == O_constant)
732 S_SET_SIZE (sym, exp.X_add_number);
733 else
734 {
735 #if 0
736 static int warned;
737 if (!warned)
738 {
739 as_tsktsk (".size expressions not yet supported, ignored");
740 warned++;
741 }
742 #endif
743 }
744 demand_empty_rest_of_line ();
745 }
746
747 static void
748 obj_elf_type (ignore)
749 int ignore;
750 {
751 char *name = input_line_pointer;
752 char c = get_symbol_end ();
753 char *p;
754 int type = 0;
755 symbolS *sym;
756
757 p = input_line_pointer;
758 *p = c;
759 SKIP_WHITESPACE ();
760 if (*input_line_pointer != ',')
761 {
762 as_bad ("expected comma after name in .type directive");
763 egress:
764 ignore_rest_of_line ();
765 return;
766 }
767 input_line_pointer++;
768 SKIP_WHITESPACE ();
769 if (*input_line_pointer != '#' && *input_line_pointer != '@')
770 {
771 as_bad ("expected `#' or `@' after comma in .type directive");
772 goto egress;
773 }
774 input_line_pointer++;
775 if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1))
776 {
777 type = BSF_FUNCTION;
778 input_line_pointer += sizeof ("function") - 1;
779 }
780 else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1))
781 {
782 input_line_pointer += sizeof ("object") - 1;
783 }
784 else
785 {
786 as_bad ("unrecognized symbol type, ignored");
787 goto egress;
788 }
789 demand_empty_rest_of_line ();
790 *p = 0;
791 sym = symbol_find_or_make (name);
792 sym->bsym->flags |= type;
793 }
794
795 static void
796 obj_elf_ident (ignore)
797 int ignore;
798 {
799 static segT comment_section;
800 segT old_section = now_seg;
801 int old_subsection = now_subseg;
802
803 if (!comment_section)
804 {
805 char *p;
806 comment_section = subseg_new (".comment", 0);
807 bfd_set_section_flags (stdoutput, comment_section,
808 SEC_READONLY | SEC_HAS_CONTENTS);
809 p = frag_more (1);
810 *p = 0;
811 }
812 else
813 subseg_set (comment_section, 0);
814 stringer (1);
815 subseg_set (old_section, old_subsection);
816 }
817
818 /* The first entry in a .stabs section is special. */
819
820 void
821 obj_elf_init_stab_section (seg)
822 segT seg;
823 {
824 char *file;
825 char *p;
826 unsigned int stroff;
827
828 /* Force the section to align to a longword boundary. Without this,
829 UnixWare ar crashes. */
830 bfd_set_section_alignment (stdoutput, seg, 2);
831
832 p = frag_more (12);
833 as_where (&file, (unsigned int *) NULL);
834 stroff = get_stab_string_offset (file, segment_name (seg));
835 know (stroff == 1);
836 md_number_to_chars (p, stroff, 4);
837 seg_info (seg)->stabu.p = p;
838 }
839
840 /* Fill in the counts in the first entry in a .stabs section. */
841
842 static void
843 adjust_stab_sections (abfd, sec, xxx)
844 bfd *abfd;
845 asection *sec;
846 PTR xxx;
847 {
848 char *name;
849 asection *strsec;
850 char *p;
851 int strsz, nsyms;
852
853 if (strncmp (".stab", sec->name, 5))
854 return;
855 if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
856 return;
857
858 name = (char *) alloca (strlen (sec->name) + 4);
859 strcpy (name, sec->name);
860 strcat (name, "str");
861 strsec = bfd_get_section_by_name (abfd, name);
862 if (strsec)
863 strsz = bfd_section_size (abfd, strsec);
864 else
865 strsz = 0;
866 nsyms = bfd_section_size (abfd, sec) / 12 - 1;
867
868 p = seg_info (sec)->stabu.p;
869 assert (p != 0);
870
871 bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
872 bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
873 }
874
875 void
876 elf_frob_file ()
877 {
878 bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
879
880 #ifdef elf_tc_symbol
881 {
882 int i;
883
884 for (i = 0; i < stdoutput->symcount; i++)
885 elf_tc_symbol (stdoutput, (PTR) (stdoutput->outsymbols[i]),
886 i + 1);
887 }
888 #endif
889
890 #ifdef elf_tc_final_processing
891 elf_tc_final_processing ();
892 #endif
893
894 /* Finally, we must make any target-specific sections. */
895
896 #ifdef elf_tc_make_sections
897 elf_tc_make_sections (stdoutput);
898 #endif
899 }
This page took 0.048745 seconds and 4 git commands to generate.