]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/obj-elf.c
gcc lint. See ChangeLog for details. Also:
[thirdparty/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 "aout/stab_gnu.h"
23 #include "obstack.h"
24
25 static void obj_elf_stab PARAMS ((int what));
26 static void obj_elf_xstab PARAMS ((int what));
27 static void obj_elf_line PARAMS ((void));
28 void obj_elf_desc PARAMS ((void));
29 void obj_elf_version PARAMS ((void));
30 static void obj_elf_size PARAMS ((void));
31 static void obj_elf_type PARAMS ((void));
32 static void obj_elf_ident PARAMS ((void));
33 static void obj_elf_weak PARAMS ((void));
34 static void obj_elf_local PARAMS ((void));
35 static void obj_elf_common PARAMS ((void));
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 {"desc", obj_elf_desc, 0},
51 {"line", obj_elf_line, 0},
52 {"stabd", obj_elf_stab, 'd'},
53 {"stabn", obj_elf_stab, 'n'},
54 {"stabs", obj_elf_stab, 's'},
55 /* This is used on Solaris 2.x on SPARC, but not supported yet. */
56 {"xstabs", obj_elf_xstab, 's'},
57
58 /* These are used for dwarf. */
59 {"2byte", cons, 2},
60 {"4byte", cons, 4},
61 {"8byte", cons, 8},
62
63 {NULL} /* end sentinel */
64 };
65
66 #undef NO_RELOC
67 #include "aout/aout64.h"
68
69 void
70 elf_file_symbol (s)
71 char *s;
72 {
73 symbolS *sym;
74
75 sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
76 sym->sy_frag = &zero_address_frag;
77 sym->bsym->flags |= BSF_FILE;
78
79 if (symbol_rootP != sym)
80 {
81 symbol_remove (sym, &symbol_rootP, &symbol_lastP);
82 symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
83 #ifdef DEBUG
84 verify_symbol_chain (symbol_rootP, symbol_lastP);
85 #endif
86 }
87 }
88
89 static void
90 obj_elf_common ()
91 {
92 char *name;
93 char c;
94 char *p;
95 int temp, size;
96 symbolS *symbolP;
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 {
138 as_bad ("Expected comma after common length");
139 ignore_rest_of_line ();
140 return;
141 }
142 input_line_pointer++;
143 SKIP_WHITESPACE ();
144 if (*input_line_pointer != '"')
145 {
146 temp = get_absolute_expression ();
147 if (temp < 0)
148 {
149 temp = 0;
150 as_warn ("Common alignment negative; 0 assumed");
151 }
152 if (symbolP->local)
153 {
154 segT old_sec;
155 int old_subsec;
156 char *p;
157 int align;
158
159 /* allocate_bss: */
160 old_sec = now_seg;
161 old_subsec = now_subseg;
162 align = temp;
163 record_alignment (bss_section, align);
164 subseg_set (bss_section, 0);
165 if (align)
166 frag_align (align, 0);
167 if (S_GET_SEGMENT (symbolP) == bss_section)
168 symbolP->sy_frag->fr_symbol = 0;
169 symbolP->sy_frag = frag_now;
170 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
171 (char *) 0);
172 *p = 0;
173 S_SET_SEGMENT (symbolP, bss_section);
174 S_CLEAR_EXTERNAL (symbolP);
175 subseg_set (old_sec, old_subsec);
176 }
177 else
178 {
179 allocate_common:
180 S_SET_VALUE (symbolP, size);
181 S_SET_EXTERNAL (symbolP);
182 /* should be common, but this is how gas does it for now */
183 S_SET_SEGMENT (symbolP, &bfd_und_section);
184 }
185 }
186 else
187 {
188 input_line_pointer++;
189 /* @@ Some use the dot, some don't. Can we get some consistency?? */
190 if (*input_line_pointer == '.')
191 input_line_pointer++;
192 /* @@ Some say data, some say bss. */
193 if (strncmp (input_line_pointer, "bss\"", 4)
194 && strncmp (input_line_pointer, "data\"", 5))
195 {
196 while (*--input_line_pointer != '"')
197 ;
198 input_line_pointer--;
199 goto bad_common_segment;
200 }
201 while (*input_line_pointer++ != '"')
202 ;
203 goto allocate_common;
204 }
205 demand_empty_rest_of_line ();
206 return;
207
208 {
209 bad_common_segment:
210 p = input_line_pointer;
211 while (*p && *p != '\n')
212 p++;
213 c = *p;
214 *p = '\0';
215 as_bad ("bad .common segment %s", input_line_pointer + 1);
216 *p = c;
217 input_line_pointer = p;
218 ignore_rest_of_line ();
219 return;
220 }
221 }
222
223 static void
224 obj_elf_local ()
225 {
226 char *name;
227 int c;
228 symbolS *symbolP;
229
230 do
231 {
232 name = input_line_pointer;
233 c = get_symbol_end ();
234 symbolP = symbol_find_or_make (name);
235 *input_line_pointer = c;
236 SKIP_WHITESPACE ();
237 S_CLEAR_EXTERNAL (symbolP);
238 symbolP->local = 1;
239 if (c == ',')
240 {
241 input_line_pointer++;
242 SKIP_WHITESPACE ();
243 if (*input_line_pointer == '\n')
244 c = '\n';
245 }
246 }
247 while (c == ',');
248 demand_empty_rest_of_line ();
249 }
250
251 static void
252 obj_elf_weak ()
253 {
254 char *name;
255 int c;
256 symbolS *symbolP;
257
258 do
259 {
260 name = input_line_pointer;
261 c = get_symbol_end ();
262 symbolP = symbol_find_or_make (name);
263 *input_line_pointer = c;
264 SKIP_WHITESPACE ();
265 S_SET_WEAK (symbolP);
266 symbolP->local = 1;
267 if (c == ',')
268 {
269 input_line_pointer++;
270 SKIP_WHITESPACE ();
271 if (*input_line_pointer == '\n')
272 c = '\n';
273 }
274 }
275 while (c == ',');
276 demand_empty_rest_of_line ();
277 }
278
279 static segT previous_section;
280 static int previous_subsection;
281
282 void
283 obj_elf_section (xxx)
284 int xxx;
285 {
286 char *string;
287 asection *sec;
288
289 /* Initialize this with inclusive-or of all flags that can be cleared
290 by attributes, but not set by them. Also include flags that won't
291 get set properly in the assembler, but which the user/compiler
292 shouldn't be expected to set. */
293 flagword flags = SEC_READONLY | SEC_ALLOC | SEC_RELOC;
294 /* Initialize this with the default flags to be used if none are
295 specified. */
296 flagword default_flags = 0;
297
298 SKIP_WHITESPACE ();
299 /* Get name of section. */
300 if (*input_line_pointer == '"')
301 string = demand_copy_C_string (&xxx);
302 else
303 {
304 char *p = input_line_pointer;
305 char c;
306 while (0 == strchr ("\n\t,; ", *p))
307 p++;
308 c = *p;
309 *p = 0;
310 string = xmalloc (p - input_line_pointer + 1);
311 strcpy (string, input_line_pointer);
312 *p = c;
313 input_line_pointer = p;
314 }
315 if (!strcmp (string, ".rodata"))
316 default_flags = SEC_ALLOC | SEC_READONLY | SEC_RELOC | SEC_LOAD;
317 else if (!strcmp (string, ".init")
318 || !strcmp (string, ".fini"))
319 default_flags = SEC_ALLOC | SEC_READONLY | SEC_RELOC | SEC_CODE | SEC_LOAD;
320
321 SKIP_WHITESPACE ();
322 if (*input_line_pointer != ',')
323 flags = default_flags;
324 while (*input_line_pointer == ',')
325 {
326 flagword bit;
327 int len, inv;
328 char *p, oldp;
329
330 input_line_pointer++;
331
332 /* Under i386-svr4, gcc emits a string here. I don't know what this
333 string is supposed to signify or how to handle it. Ignore it for
334 now, unless it becomes a problem. */
335 if (*input_line_pointer == '"')
336 {
337 demand_copy_C_string (&xxx);
338 SKIP_WHITESPACE ();
339 continue;
340 }
341
342 if (*input_line_pointer != '#' && *input_line_pointer != '@')
343 {
344 as_bad ("unrecognized syntax in .section command");
345 ignore_rest_of_line ();
346 break;
347 }
348 input_line_pointer++;
349
350 #define CHECK(X,BIT,NEG) \
351 if (!strncmp(X,input_line_pointer,len = sizeof(X) - 1)) { \
352 bit = BIT; inv = NEG; goto match; }
353
354 CHECK ("write", SEC_READONLY, 1);
355 CHECK ("alloc", SEC_ALLOC, 0);
356 CHECK ("execinstr", SEC_CODE, 1);
357 CHECK ("progbits", SEC_LOAD, 1);
358 #undef CHECK
359
360 p = input_line_pointer;
361 while (!is_end_of_line[(unsigned char) *p] && *p != 0 && *p != ',')
362 p++;
363 *p = 0;
364 oldp = *p;
365 as_bad ("unrecognized section attribute `%s' ignored",
366 input_line_pointer);
367 *p = oldp;
368 continue;
369
370 match:
371 if (inv)
372 flags &= ~bit;
373 else
374 flags |= bit;
375 input_line_pointer += len;
376 }
377 demand_empty_rest_of_line ();
378
379 /* If the C string wasn't valid, `string' could be null. */
380 if (!string)
381 return;
382
383 sec = bfd_get_section_by_name (stdoutput, string);
384 if (sec == 0)
385 {
386 sec = subseg_new (string, 0);
387 bfd_set_section_flags (stdoutput, sec, flags);
388 sec->output_section = sec;
389 }
390 previous_section = now_seg;
391 previous_subsection = now_subseg;
392 subseg_set (sec, 0);
393 }
394
395 void
396 obj_elf_previous ()
397 {
398 if (previous_section == 0)
399 {
400 as_bad (".previous without corresponding .section; ignored");
401 return;
402 }
403 subseg_set (previous_section, previous_subsection);
404 previous_section = 0;
405 }
406
407 int
408 obj_elf_write_symbol_p (sym)
409 symbolS *sym;
410 {
411 /* If this is a local symbol, are there any relocations for which
412 need this symbol? */
413
414 /* To find this out, we examine all relocations in all bfd sections
415 that have relocations. If there is one that references this
416 symbol, we need to keep this symbol. In this case, we return a
417 true status. In all other cases, we return a false status. */
418
419 if (S_IS_LOCAL (sym))
420 {
421 asymbol *bsym = sym->bsym;
422 bfd *abfd = bsym->the_bfd;
423 asection *bsec;
424
425 for (bsec = abfd->sections; bsec; bsec = bsec->next)
426 {
427 struct reloc_cache_entry **rlocs = bsec->orelocation;
428 int rcnt = bsec->reloc_count;
429
430 if (rlocs)
431 {
432 int i;
433
434 for (i = 0; i < rcnt; i++)
435 if (rlocs[i]->sym_ptr_ptr
436 && rlocs[i]->sym_ptr_ptr[0] == bsym)
437 return 1;
438 }
439 else
440 {
441 /* No relocations for this section. Check the seg_info
442 structure to see if there are any fixups for this
443 section. */
444 segment_info_type *seginfo = seg_info (bsec);
445 fixS *fixp;
446
447 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
448 if ((fixp->fx_addsy && fixp->fx_addsy->bsym == bsym)
449 || (fixp->fx_subsy && fixp->fx_subsy->bsym == bsym))
450 return 1;
451 }
452 }
453 }
454 return 0;
455 }
456
457 int
458 obj_elf_write_symbol (sym)
459 symbolS *sym;
460 {
461 return /* obj_elf_write_symbol_p (sym) || */ !S_IS_LOCAL (sym);
462 }
463
464 int
465 obj_elf_frob_symbol (sym, punt)
466 symbolS *sym;
467 int *punt;
468 {
469 #if 0 /* ?? The return value is ignored. Only the value of *punt is
470 relevant. */
471 return obj_elf_write_symbol_p (sym);
472 #endif
473 /* FIXME: Just return 0 until is fixed. */
474 return 0;
475 }
476
477 static void
478 obj_elf_line ()
479 {
480 /* Assume delimiter is part of expression. BSD4.2 as fails with
481 delightful bug, so we are not being incompatible here. */
482 new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
483 demand_empty_rest_of_line ();
484 }
485
486 /*
487 * stab()
488 *
489 * Handle .stabX directives, which used to be open-coded.
490 * So much creeping featurism overloaded the semantics that we decided
491 * to put all .stabX thinking in one place. Here.
492 *
493 * We try to make any .stabX directive legal. Other people's AS will often
494 * do assembly-time consistency checks: eg assigning meaning to n_type bits
495 * and "protecting" you from setting them to certain values. (They also zero
496 * certain bits before emitting symbols. Tut tut.)
497 *
498 * If an expression is not absolute we either gripe or use the relocation
499 * information. Other people's assemblers silently forget information they
500 * don't need and invent information they need that you didn't supply.
501 *
502 * .stabX directives always make a symbol table entry. It may be junk if
503 * the rest of your .stabX directive is malformed.
504 */
505
506 /*
507 * elf_stab_symbol_string()
508 *
509 * Build a string dictionary entry for a .stabX symbol.
510 * The symbol is added to the .stabstr section.
511 *
512 */
513
514 static unsigned int
515 elf_stab_symbol_string (string, secname)
516 char *string, *secname;
517 {
518 asection *save_seg;
519 asection *seg;
520 subsegT save_subseg;
521 unsigned int length;
522 unsigned int old_gdb_string_index;
523 char *clengthP;
524 int i;
525 char c;
526 /* @@FIXME -- there should be no static data here!
527 This also has the effect of making all stab string tables large enough
528 to contain all the contents written to any of them. This only matters
529 with the Solaris native compiler for the moment, but it should be fixed
530 anyways. */
531 static unsigned int gdb_string_index = 0;
532
533 old_gdb_string_index = 0;
534 length = strlen (string);
535 clengthP = (char *) &length;
536 if (length > 0)
537 { /* Ordinary case. */
538 save_seg = now_seg;
539 save_subseg = now_subseg;
540
541 /* Create the stab sections, if they are not already created. */
542 {
543 char *newsecname = xmalloc (strlen (secname) + 4);
544 strcpy (newsecname, secname);
545 strcat (newsecname, "str");
546 seg = bfd_get_section_by_name (stdoutput, newsecname);
547 if (seg == 0)
548 {
549 seg = bfd_make_section_old_way (stdoutput, newsecname);
550 bfd_set_section_flags (stdoutput, seg,
551 SEC_LOAD | SEC_READONLY | SEC_ALLOC);
552 }
553 /* free (newsecname);*/
554 }
555 subseg_new ((char *) seg->name, save_subseg);
556 old_gdb_string_index = gdb_string_index;
557 i = 0;
558 while ((c = *string++))
559 {
560 i++;
561 gdb_string_index++;
562 FRAG_APPEND_1_CHAR (c);
563 }
564 {
565 FRAG_APPEND_1_CHAR ((char) 0);
566 i++;
567 gdb_string_index++;
568 }
569 while (i % 4 != 0)
570 {
571 FRAG_APPEND_1_CHAR ((char) 0);
572 i++;
573 gdb_string_index++;
574 }
575 subseg_new ((char *) save_seg->name, save_subseg);
576 }
577
578 return old_gdb_string_index;
579 }
580
581 static void
582 DEFUN (elf_stab_symbol, (symbolP, stab_type),
583 symbolS *symbolP AND
584 int stab_type)
585 {
586 char *toP;
587
588 toP = frag_more (8);
589 /* the string index portion of the stab */
590 md_number_to_chars (toP, (valueT) symbolP->sy_name_offset, 4);
591 md_number_to_chars (toP + 4, (valueT) S_GET_TYPE (symbolP), 1);
592 md_number_to_chars (toP + 5, (valueT) S_GET_OTHER (symbolP), 1);
593 md_number_to_chars (toP + 6, (valueT) S_GET_DESC (symbolP), 2);
594 /* The n_value field doesn't get written here, it gets done below. It
595 may be an expression needing relocating. */
596 }
597
598 static void
599 obj_elf_stab_generic (what, secname)
600 int what;
601 char *secname;
602 {
603 extern int listing;
604
605 symbolS *symbolP = 0;
606 char *string;
607 int saved_type = 0;
608 int length;
609 int goof = 0;
610 int seg_is_new = 0;
611 long longint;
612 asection *saved_seg = now_seg;
613 asection *seg;
614 subsegT subseg = now_subseg;
615
616 #if 0
617 /* This function doesn't work yet.
618
619 Actually, this function is okay, but some finalizations are
620 needed before writing the object file; that's not done yet, and
621 the Solaris linker chokes without it.
622
623 In any case, this should effectively disable it for now. */
624 if (what == 's')
625 demand_copy_C_string (&length);
626 s_ignore (69);
627 return;
628 #endif
629
630 seg = bfd_get_section_by_name (stdoutput, secname);
631 if (seg == 0)
632 {
633 seg = subseg_new (secname, 0);
634 bfd_set_section_flags (stdoutput, seg,
635 SEC_LOAD | SEC_READONLY | SEC_ALLOC | SEC_RELOC);
636 subseg_set (saved_seg, subseg);
637 seg_is_new = 1;
638 }
639
640 /*
641 * Enter with input_line_pointer pointing past .stabX and any following
642 * whitespace.
643 */
644 if (what == 's')
645 {
646 string = demand_copy_C_string (&length);
647 SKIP_WHITESPACE ();
648 if (*input_line_pointer == ',')
649 input_line_pointer++;
650 else
651 {
652 as_bad ("I need a comma after symbol's name");
653 goof = 1;
654 }
655 }
656 else
657 string = "";
658
659 /*
660 * Input_line_pointer->after ','. String->symbol name.
661 */
662 if (!goof)
663 {
664 symbolP = symbol_new (string, &bfd_und_section, (valueT) 0, (struct frag *) 0);
665
666 /* enter the string in the .stab string table (section .stabstr) */
667 symbolP->sy_name_offset = elf_stab_symbol_string (string, secname);
668
669 switch (what)
670 {
671 case 'd':
672 S_SET_NAME (symbolP, NULL); /* .stabd feature. */
673 S_SET_VALUE (symbolP,
674 (valueT) ((char*) obstack_next_free (&frags) - frag_now->fr_literal));
675 S_SET_SEGMENT (symbolP, now_seg);
676 symbolP->sy_frag = frag_now;
677 break;
678
679 case 'n':
680 symbolP->sy_frag = &zero_address_frag;
681 break;
682
683 case 's':
684 symbolP->sy_frag = &zero_address_frag;
685 break;
686
687 default:
688 BAD_CASE (what);
689 break;
690 }
691
692 if (get_absolute_expression_and_terminator (&longint) == ',')
693 {
694 saved_type = longint;
695 S_SET_TYPE (symbolP, saved_type);
696 }
697 else
698 {
699 as_bad ("I want a comma after the n_type expression");
700 goof = 1;
701 input_line_pointer--; /* Backup over a non-',' char. */
702 }
703 }
704
705 if (!goof)
706 {
707 if (get_absolute_expression_and_terminator (&longint) == ',')
708 S_SET_OTHER (symbolP, longint);
709 else
710 {
711 as_bad ("I want a comma after the n_other expression");
712 goof = 1;
713 input_line_pointer--; /* Backup over a non-',' char. */
714 }
715 }
716
717 if (!goof)
718 {
719 S_SET_DESC (symbolP, get_absolute_expression ());
720 if (what == 's' || what == 'n')
721 {
722 if (*input_line_pointer != ',')
723 {
724 as_bad ("I want a comma after the n_desc expression");
725 goof = 1;
726 }
727 else
728 {
729 input_line_pointer++;
730 }
731 }
732 }
733
734 if (goof)
735 {
736 ignore_rest_of_line ();
737 return;
738 }
739
740 subseg_new ((char *) seg->name, subseg);
741
742 if (seg_is_new)
743 /* allocate and discard -- filled in later */
744 (void) frag_more (12);
745
746 /* Emit the stab symbol. */
747 elf_stab_symbol (symbolP, what);
748
749 if (what == 's' || what == 'n')
750 {
751 cons (4);
752 input_line_pointer--;
753 }
754 else
755 {
756 char *p = frag_more (4);
757 md_number_to_chars (p, 0, 4);
758 }
759
760 subseg_new ((char *) saved_seg->name, subseg);
761
762 if ((what == 's' || what == 'n')
763 && symbolP->sy_value.X_op == O_constant)
764 {
765 /* symbol is not needed in the regular symbol table */
766 symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
767 }
768
769 if (what == 's' && S_GET_TYPE (symbolP) == N_SO)
770 {
771 fragS *fragp = seg_info (seg)->frchainP->frch_root;
772 while (fragp
773 && fragp->fr_address + fragp->fr_fix < 12)
774 fragp = fragp->fr_next;
775 assert (fragp != 0);
776 assert (fragp->fr_type == rs_fill);
777 assert (fragp->fr_address == 0 && fragp->fr_fix >= 12);
778 md_number_to_chars (fragp->fr_literal, (valueT) symbolP->sy_name_offset,
779 4);
780 }
781
782 if (listing)
783 switch (S_GET_TYPE (symbolP))
784 {
785 case N_SLINE:
786 listing_source_line (S_GET_DESC (symbolP));
787 break;
788 case N_SO:
789 case N_SOL:
790 listing_source_file (string);
791 break;
792 }
793
794 demand_empty_rest_of_line ();
795 }
796
797 static void
798 obj_elf_stab (what)
799 int what;
800 {
801 obj_elf_stab_generic (what, ".stab");
802 }
803
804 static void
805 obj_elf_xstab (what)
806 int what;
807 {
808 int length;
809 char *secname;
810
811 secname = demand_copy_C_string (&length);
812 SKIP_WHITESPACE ();
813 if (*input_line_pointer == ',')
814 input_line_pointer++;
815 else
816 {
817 as_bad ("comma missing in .xstabs");
818 ignore_rest_of_line ();
819 return;
820 }
821 obj_elf_stab_generic (what, secname);
822 }
823
824 void
825 obj_elf_desc ()
826 {
827 char *name;
828 char c;
829 char *p;
830 symbolS *symbolP;
831 int temp;
832
833 /* Frob invented at RMS' request. Set the n_desc of a symbol. */
834 name = input_line_pointer;
835 c = get_symbol_end ();
836 p = input_line_pointer;
837 *p = c;
838 SKIP_WHITESPACE ();
839 if (*input_line_pointer != ',')
840 {
841 *p = 0;
842 as_bad ("Expected comma after name \"%s\"", name);
843 *p = c;
844 ignore_rest_of_line ();
845 }
846 else
847 {
848 input_line_pointer++;
849 temp = get_absolute_expression ();
850 *p = 0;
851 symbolP = symbol_find_or_make (name);
852 *p = c;
853 S_SET_DESC (symbolP, temp);
854 }
855 demand_empty_rest_of_line ();
856 } /* obj_elf_desc() */
857
858 void
859 obj_read_begin_hook ()
860 {
861 }
862
863 void
864 obj_symbol_new_hook (symbolP)
865 symbolS *symbolP;
866 {
867 #if 0 /* BFD already takes care of this */
868 elf32_symbol_type *esym = (elf32_symbol_type *) symbolP;
869
870 /* There is an Elf_Internal_Sym and an Elf_External_Sym. For now,
871 just zero them out. */
872
873 bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym));
874 bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym));
875 bzero ((char *) &esym->tc_data, sizeof (esym->tc_data));
876 #endif
877 }
878
879 void
880 obj_elf_version ()
881 {
882 char *name;
883 unsigned int c;
884 char ch;
885 char *p;
886 asection *seg = now_seg;
887 subsegT subseg = now_subseg;
888 Elf_Internal_Note i_note;
889 Elf_External_Note e_note;
890 asection *note_secp = (asection *) NULL;
891 int i, len;
892
893 SKIP_WHITESPACE ();
894 if (*input_line_pointer == '\"')
895 {
896 ++input_line_pointer; /* -> 1st char of string. */
897 name = input_line_pointer;
898
899 while (is_a_char (c = next_char_of_string ()))
900 ;
901 c = *input_line_pointer;
902 *input_line_pointer = '\0';
903 *(input_line_pointer - 1) = '\0';
904 *input_line_pointer = c;
905
906 /* create the .note section if this is the first version string */
907
908 note_secp = bfd_get_section_by_name (stdoutput, ".note");
909 if (note_secp == (asection *) NULL)
910 {
911 note_secp = bfd_make_section_old_way (stdoutput, ".note");
912 bfd_set_section_flags (stdoutput,
913 note_secp,
914 SEC_LOAD | SEC_HAS_CONTENTS | SEC_READONLY);
915 }
916
917 /* process the version string */
918
919 subseg_new ((char *) note_secp->name, 0);
920 len = strlen (name);
921
922 i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
923 i_note.descsz = 0; /* no description */
924 i_note.type = NT_VERSION;
925 p = frag_more (sizeof (e_note.namesz));
926 md_number_to_chars (p, (valueT) i_note.namesz, 4);
927 p = frag_more (sizeof (e_note.descsz));
928 md_number_to_chars (p, (valueT) i_note.descsz, 4);
929 p = frag_more (sizeof (e_note.type));
930 md_number_to_chars (p, (valueT) i_note.type, 4);
931
932 for (i = 0; i < len; i++)
933 {
934 ch = *(name + i);
935 {
936 FRAG_APPEND_1_CHAR (ch);
937 }
938 }
939 frag_align (2, 0);
940
941 subseg_new ((char *) seg->name, subseg);
942 }
943 else
944 {
945 as_bad ("Expected quoted string");
946 }
947 demand_empty_rest_of_line ();
948 }
949
950 static void
951 obj_elf_size ()
952 {
953 char *name = input_line_pointer;
954 char c = get_symbol_end ();
955 char *p;
956 expressionS exp;
957 symbolS *sym;
958
959 p = input_line_pointer;
960 *p = c;
961 SKIP_WHITESPACE ();
962 if (*input_line_pointer != ',')
963 {
964 *p = 0;
965 as_bad ("expected comma after name `%s' in .size directive", name);
966 *p = c;
967 ignore_rest_of_line ();
968 return;
969 }
970 input_line_pointer++;
971 expression (&exp);
972 if (exp.X_op == O_absent)
973 {
974 as_bad ("missing expression in .size directive");
975 exp.X_op = O_constant;
976 exp.X_add_number = 0;
977 }
978 *p = 0;
979 sym = symbol_find_or_make (name);
980 *p = c;
981 if (exp.X_op == O_constant)
982 S_SET_SIZE (sym, exp.X_add_number);
983 else
984 {
985 #if 0
986 static int warned;
987 if (!warned)
988 {
989 as_tsktsk (".size expressions not yet supported, ignored");
990 warned++;
991 }
992 #endif
993 }
994 demand_empty_rest_of_line ();
995 }
996
997 static void
998 obj_elf_type ()
999 {
1000 char *name = input_line_pointer;
1001 char c = get_symbol_end ();
1002 char *p;
1003 int type = 0;
1004 symbolS *sym;
1005
1006 p = input_line_pointer;
1007 *p = c;
1008 SKIP_WHITESPACE ();
1009 if (*input_line_pointer != ',')
1010 {
1011 as_bad ("expected comma after name in .type directive");
1012 egress:
1013 ignore_rest_of_line ();
1014 return;
1015 }
1016 input_line_pointer++;
1017 SKIP_WHITESPACE ();
1018 if (*input_line_pointer != '#' && *input_line_pointer != '@')
1019 {
1020 as_bad ("expected `#' or `@' after comma in .type directive");
1021 goto egress;
1022 }
1023 input_line_pointer++;
1024 if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1))
1025 {
1026 type = BSF_FUNCTION;
1027 input_line_pointer += sizeof ("function") - 1;
1028 }
1029 else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1))
1030 {
1031 input_line_pointer += sizeof ("object") - 1;
1032 }
1033 else
1034 {
1035 as_bad ("unrecognized symbol type, ignored");
1036 goto egress;
1037 }
1038 demand_empty_rest_of_line ();
1039 *p = 0;
1040 sym = symbol_find_or_make (name);
1041 sym->bsym->flags |= type;
1042 }
1043
1044 static void
1045 obj_elf_ident ()
1046 {
1047 static segT comment_section;
1048 segT old_section = now_seg;
1049 int old_subsection = now_subseg;
1050
1051 if (!comment_section)
1052 {
1053 char *p;
1054 comment_section = subseg_new (".comment", 0);
1055 bfd_set_section_flags (stdoutput, comment_section, SEC_HAS_CONTENTS);
1056 p = frag_more (1);
1057 *p = 0;
1058 }
1059 else
1060 subseg_set (comment_section, 0);
1061 stringer (1);
1062 subseg_set (old_section, old_subsection);
1063 }
1064
1065 static void
1066 adjust_stab_sections (abfd, sec, xxx)
1067 bfd *abfd;
1068 asection *sec;
1069 PTR xxx;
1070 {
1071 char *name;
1072 asection *strsec;
1073 fragS *fragp;
1074 int strsz, nsyms;
1075
1076 if (strncmp (".stab", sec->name, 5))
1077 return;
1078 if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
1079 return;
1080
1081 name = (char *) alloca (strlen (sec->name) + 4);
1082 strcpy (name, sec->name);
1083 strcat (name, "str");
1084 strsec = bfd_get_section_by_name (abfd, name);
1085 if (strsec)
1086 strsz = bfd_section_size (abfd, strsec);
1087 else
1088 strsz = 0;
1089 nsyms = bfd_section_size (abfd, sec) / 12 - 1;
1090
1091 fragp = seg_info (sec)->frchainP->frch_root;
1092 while (fragp
1093 && fragp->fr_address + fragp->fr_fix < 12)
1094 fragp = fragp->fr_next;
1095 assert (fragp != 0);
1096 assert (fragp->fr_type == rs_fill);
1097 assert (fragp->fr_address == 0 && fragp->fr_fix >= 12);
1098
1099 bfd_h_put_16 (abfd, nsyms, fragp->fr_literal + 6);
1100 bfd_h_put_32 (abfd, strsz, fragp->fr_literal + 8);
1101 }
1102
1103 void
1104 elf_frob_file ()
1105 {
1106 bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
1107
1108 #ifdef elf_tc_symbol
1109 {
1110 int i;
1111
1112 for (i = 0; i < stdoutput->symcount; i++)
1113 elf_tc_symbol (stdoutput, (PTR) (stdoutput->outsymbols[i]),
1114 i + 1);
1115 }
1116 #endif
1117
1118 #ifdef elf_tc_final_processing
1119 elf_tc_final_processing ();
1120 #endif
1121
1122 /* Finally, we must make any target-specific sections. */
1123
1124 #ifdef elf_tc_make_sections
1125 elf_tc_make_sections (stdoutput);
1126 #endif
1127 }