Some more gcc lint, and:
[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
35 const pseudo_typeS obj_pseudo_table[] =
36 {
37 {"comm", obj_elf_common, 0},
38 {"ident", obj_elf_ident, 0},
39 {"local", obj_elf_local, 0},
40 {"previous", obj_elf_previous, 0},
41 {"section", obj_elf_section, 0},
42 {"size", obj_elf_size, 0},
43 {"type", obj_elf_type, 0},
44 {"version", obj_elf_version, 0},
45 {"weak", obj_elf_weak, 0},
46
47 /* These are used for stabs-in-elf configurations. */
48 {"line", obj_elf_line, 0},
49
50 /* These are used for dwarf. */
51 {"2byte", cons, 2},
52 {"4byte", cons, 4},
53 {"8byte", cons, 8},
54
55 {NULL} /* end sentinel */
56 };
57
58 #undef NO_RELOC
59 #include "aout/aout64.h"
60
61 void
62 elf_file_symbol (s)
63 char *s;
64 {
65 symbolS *sym;
66
67 sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
68 sym->sy_frag = &zero_address_frag;
69 sym->bsym->flags |= BSF_FILE;
70
71 if (symbol_rootP != sym)
72 {
73 symbol_remove (sym, &symbol_rootP, &symbol_lastP);
74 symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
75 #ifdef DEBUG
76 verify_symbol_chain (symbol_rootP, symbol_lastP);
77 #endif
78 }
79 }
80
81 static void
82 obj_elf_common (ignore)
83 int ignore;
84 {
85 char *name;
86 char c;
87 char *p;
88 int temp, size;
89 symbolS *symbolP;
90
91 name = input_line_pointer;
92 c = get_symbol_end ();
93 /* just after name is now '\0' */
94 p = input_line_pointer;
95 *p = c;
96 SKIP_WHITESPACE ();
97 if (*input_line_pointer != ',')
98 {
99 as_bad ("Expected comma after symbol-name");
100 ignore_rest_of_line ();
101 return;
102 }
103 input_line_pointer++; /* skip ',' */
104 if ((temp = get_absolute_expression ()) < 0)
105 {
106 as_bad (".COMMon length (%d.) <0! Ignored.", temp);
107 ignore_rest_of_line ();
108 return;
109 }
110 size = temp;
111 *p = 0;
112 symbolP = symbol_find_or_make (name);
113 *p = c;
114 if (S_IS_DEFINED (symbolP))
115 {
116 as_bad ("Ignoring attempt to re-define symbol");
117 ignore_rest_of_line ();
118 return;
119 }
120 if (S_GET_VALUE (symbolP) != 0)
121 {
122 if (S_GET_VALUE (symbolP) != size)
123 {
124 as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
125 S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
126 }
127 }
128 know (symbolP->sy_frag == &zero_address_frag);
129 if (*input_line_pointer != ',')
130 {
131 as_bad ("Expected comma after common length");
132 ignore_rest_of_line ();
133 return;
134 }
135 input_line_pointer++;
136 SKIP_WHITESPACE ();
137 if (*input_line_pointer != '"')
138 {
139 temp = get_absolute_expression ();
140 if (temp < 0)
141 {
142 temp = 0;
143 as_warn ("Common alignment negative; 0 assumed");
144 }
145 if (symbolP->local)
146 {
147 segT old_sec;
148 int old_subsec;
149 char *pfrag;
150 int align;
151
152 /* allocate_bss: */
153 old_sec = now_seg;
154 old_subsec = now_subseg;
155 align = temp;
156 record_alignment (bss_section, align);
157 subseg_set (bss_section, 0);
158 if (align)
159 frag_align (align, 0);
160 if (S_GET_SEGMENT (symbolP) == bss_section)
161 symbolP->sy_frag->fr_symbol = 0;
162 symbolP->sy_frag = frag_now;
163 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
164 (char *) 0);
165 *pfrag = 0;
166 S_SET_SEGMENT (symbolP, bss_section);
167 S_CLEAR_EXTERNAL (symbolP);
168 subseg_set (old_sec, old_subsec);
169 }
170 else
171 {
172 allocate_common:
173 S_SET_VALUE (symbolP, (valueT) size);
174 S_SET_EXTERNAL (symbolP);
175 /* should be common, but this is how gas does it for now */
176 S_SET_SEGMENT (symbolP, &bfd_und_section);
177 }
178 }
179 else
180 {
181 input_line_pointer++;
182 /* @@ Some use the dot, some don't. Can we get some consistency?? */
183 if (*input_line_pointer == '.')
184 input_line_pointer++;
185 /* @@ Some say data, some say bss. */
186 if (strncmp (input_line_pointer, "bss\"", 4)
187 && strncmp (input_line_pointer, "data\"", 5))
188 {
189 while (*--input_line_pointer != '"')
190 ;
191 input_line_pointer--;
192 goto bad_common_segment;
193 }
194 while (*input_line_pointer++ != '"')
195 ;
196 goto allocate_common;
197 }
198 demand_empty_rest_of_line ();
199 return;
200
201 {
202 bad_common_segment:
203 p = input_line_pointer;
204 while (*p && *p != '\n')
205 p++;
206 c = *p;
207 *p = '\0';
208 as_bad ("bad .common segment %s", input_line_pointer + 1);
209 *p = c;
210 input_line_pointer = p;
211 ignore_rest_of_line ();
212 return;
213 }
214 }
215
216 static void
217 obj_elf_local (ignore)
218 int ignore;
219 {
220 char *name;
221 int c;
222 symbolS *symbolP;
223
224 do
225 {
226 name = input_line_pointer;
227 c = get_symbol_end ();
228 symbolP = symbol_find_or_make (name);
229 *input_line_pointer = c;
230 SKIP_WHITESPACE ();
231 S_CLEAR_EXTERNAL (symbolP);
232 symbolP->local = 1;
233 if (c == ',')
234 {
235 input_line_pointer++;
236 SKIP_WHITESPACE ();
237 if (*input_line_pointer == '\n')
238 c = '\n';
239 }
240 }
241 while (c == ',');
242 demand_empty_rest_of_line ();
243 }
244
245 static void
246 obj_elf_weak (ignore)
247 int ignore;
248 {
249 char *name;
250 int c;
251 symbolS *symbolP;
252
253 do
254 {
255 name = input_line_pointer;
256 c = get_symbol_end ();
257 symbolP = symbol_find_or_make (name);
258 *input_line_pointer = c;
259 SKIP_WHITESPACE ();
260 S_SET_WEAK (symbolP);
261 symbolP->local = 1;
262 if (c == ',')
263 {
264 input_line_pointer++;
265 SKIP_WHITESPACE ();
266 if (*input_line_pointer == '\n')
267 c = '\n';
268 }
269 }
270 while (c == ',');
271 demand_empty_rest_of_line ();
272 }
273
274 static segT previous_section;
275 static int previous_subsection;
276
277 void
278 obj_elf_section (xxx)
279 int xxx;
280 {
281 char *string;
282 asection *sec;
283
284 /* Initialize this with inclusive-or of all flags that can be cleared
285 by attributes, but not set by them. Also include flags that won't
286 get set properly in the assembler, but which the user/compiler
287 shouldn't be expected to set. */
288 flagword flags = SEC_READONLY | SEC_ALLOC | SEC_RELOC;
289 /* Initialize this with the default flags to be used if none are
290 specified. */
291 flagword default_flags = 0;
292
293 SKIP_WHITESPACE ();
294 /* Get name of section. */
295 if (*input_line_pointer == '"')
296 string = demand_copy_C_string (&xxx);
297 else
298 {
299 char *p = input_line_pointer;
300 char c;
301 while (0 == strchr ("\n\t,; ", *p))
302 p++;
303 c = *p;
304 *p = 0;
305 string = xmalloc ((unsigned long) (p - input_line_pointer + 1));
306 strcpy (string, input_line_pointer);
307 *p = c;
308 input_line_pointer = p;
309 }
310 if (!strcmp (string, ".rodata"))
311 default_flags = SEC_ALLOC | SEC_READONLY | SEC_RELOC | SEC_LOAD;
312 else if (!strcmp (string, ".init")
313 || !strcmp (string, ".fini"))
314 default_flags = SEC_ALLOC | SEC_READONLY | SEC_RELOC | SEC_CODE | SEC_LOAD;
315
316 SKIP_WHITESPACE ();
317 if (*input_line_pointer != ',')
318 flags = default_flags;
319 while (*input_line_pointer == ',')
320 {
321 flagword bit;
322 unsigned int len;
323 int inv;
324 char *p, oldp;
325
326 input_line_pointer++;
327
328 /* Under i386-svr4, gcc emits a string here. I don't know what this
329 string is supposed to signify or how to handle it. Ignore it for
330 now, unless it becomes a problem. */
331 if (*input_line_pointer == '"')
332 {
333 demand_copy_C_string (&xxx);
334 SKIP_WHITESPACE ();
335 continue;
336 }
337
338 if (*input_line_pointer != '#' && *input_line_pointer != '@')
339 {
340 as_bad ("unrecognized syntax in .section command");
341 ignore_rest_of_line ();
342 break;
343 }
344 input_line_pointer++;
345
346 #define CHECK(X,BIT,NEG) \
347 if (!strncmp(X,input_line_pointer,len = sizeof(X) - 1)) { \
348 bit = BIT; inv = NEG; goto match; }
349
350 CHECK ("write", SEC_READONLY, 1);
351 CHECK ("alloc", SEC_ALLOC, 0);
352 CHECK ("execinstr", SEC_CODE, 1);
353 CHECK ("progbits", SEC_LOAD, 1);
354 #undef CHECK
355
356 p = input_line_pointer;
357 while (!is_end_of_line[(unsigned char) *p] && *p != 0 && *p != ',')
358 p++;
359 *p = 0;
360 oldp = *p;
361 as_bad ("unrecognized section attribute `%s' ignored",
362 input_line_pointer);
363 *p = oldp;
364 continue;
365
366 match:
367 if (inv)
368 flags &= ~bit;
369 else
370 flags |= bit;
371 input_line_pointer += len;
372 }
373 demand_empty_rest_of_line ();
374
375 /* If the C string wasn't valid, `string' could be null. */
376 if (!string)
377 return;
378
379 sec = bfd_get_section_by_name (stdoutput, string);
380 if (sec == 0)
381 {
382 sec = subseg_new (string, 0);
383 bfd_set_section_flags (stdoutput, sec, flags);
384 sec->output_section = sec;
385 }
386 previous_section = now_seg;
387 previous_subsection = now_subseg;
388 subseg_set (sec, 0);
389 }
390
391 void
392 obj_elf_previous (ignore)
393 int ignore;
394 {
395 if (previous_section == 0)
396 {
397 as_bad (".previous without corresponding .section; ignored");
398 return;
399 }
400 subseg_set (previous_section, previous_subsection);
401 previous_section = 0;
402 }
403
404 static int
405 obj_elf_write_symbol_p (sym)
406 symbolS *sym;
407 {
408 /* If this is a local symbol, are there any relocations for which
409 need this symbol? */
410
411 /* To find this out, we examine all relocations in all bfd sections
412 that have relocations. If there is one that references this
413 symbol, we need to keep this symbol. In this case, we return a
414 true status. In all other cases, we return a false status. */
415
416 if (S_IS_LOCAL (sym))
417 {
418 asymbol *bsym = sym->bsym;
419 bfd *abfd = bsym->the_bfd;
420 asection *bsec;
421
422 for (bsec = abfd->sections; bsec; bsec = bsec->next)
423 {
424 struct reloc_cache_entry **rlocs = bsec->orelocation;
425 int rcnt = bsec->reloc_count;
426
427 if (rlocs)
428 {
429 int i;
430
431 for (i = 0; i < rcnt; i++)
432 if (rlocs[i]->sym_ptr_ptr
433 && rlocs[i]->sym_ptr_ptr[0] == bsym)
434 return 1;
435 }
436 else
437 {
438 /* No relocations for this section. Check the seg_info
439 structure to see if there are any fixups for this
440 section. */
441 segment_info_type *seginfo = seg_info (bsec);
442 fixS *fixp;
443
444 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
445 if ((fixp->fx_addsy && fixp->fx_addsy->bsym == bsym)
446 || (fixp->fx_subsy && fixp->fx_subsy->bsym == bsym))
447 return 1;
448 }
449 }
450 }
451 return 0;
452 }
453
454 int
455 obj_elf_write_symbol (sym)
456 symbolS *sym;
457 {
458 return /* obj_elf_write_symbol_p (sym) || */ !S_IS_LOCAL (sym);
459 }
460
461 int
462 obj_elf_frob_symbol (sym, punt)
463 symbolS *sym;
464 int *punt;
465 {
466 #if 0 /* ?? The return value is ignored. Only the value of *punt is
467 relevant. */
468 return obj_elf_write_symbol_p (sym);
469 #endif
470 /* FIXME: Just return 0 until is fixed. */
471 return 0;
472 }
473
474 static void
475 obj_elf_line (ignore)
476 int ignore;
477 {
478 /* Assume delimiter is part of expression. BSD4.2 as fails with
479 delightful bug, so we are not being incompatible here. */
480 new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
481 demand_empty_rest_of_line ();
482 }
483
484 void
485 obj_read_begin_hook ()
486 {
487 }
488
489 void
490 obj_symbol_new_hook (symbolP)
491 symbolS *symbolP;
492 {
493 #if 0 /* BFD already takes care of this */
494 elf32_symbol_type *esym = (elf32_symbol_type *) symbolP;
495
496 /* There is an Elf_Internal_Sym and an Elf_External_Sym. For now,
497 just zero them out. */
498
499 bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym));
500 bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym));
501 bzero ((char *) &esym->tc_data, sizeof (esym->tc_data));
502 #endif
503 }
504
505 void
506 obj_elf_version (ignore)
507 int ignore;
508 {
509 char *name;
510 unsigned int c;
511 char ch;
512 char *p;
513 asection *seg = now_seg;
514 subsegT subseg = now_subseg;
515 Elf_Internal_Note i_note;
516 Elf_External_Note e_note;
517 asection *note_secp = (asection *) NULL;
518 int i, len;
519
520 SKIP_WHITESPACE ();
521 if (*input_line_pointer == '\"')
522 {
523 ++input_line_pointer; /* -> 1st char of string. */
524 name = input_line_pointer;
525
526 while (is_a_char (c = next_char_of_string ()))
527 ;
528 c = *input_line_pointer;
529 *input_line_pointer = '\0';
530 *(input_line_pointer - 1) = '\0';
531 *input_line_pointer = c;
532
533 /* create the .note section */
534
535 note_secp = subseg_new (".note", 0);
536 bfd_set_section_flags (stdoutput,
537 note_secp,
538 SEC_HAS_CONTENTS | SEC_READONLY);
539
540 /* process the version string */
541
542 len = strlen (name);
543
544 i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
545 i_note.descsz = 0; /* no description */
546 i_note.type = NT_VERSION;
547 p = frag_more (sizeof (e_note.namesz));
548 md_number_to_chars (p, (valueT) i_note.namesz, 4);
549 p = frag_more (sizeof (e_note.descsz));
550 md_number_to_chars (p, (valueT) i_note.descsz, 4);
551 p = frag_more (sizeof (e_note.type));
552 md_number_to_chars (p, (valueT) i_note.type, 4);
553
554 for (i = 0; i < len; i++)
555 {
556 ch = *(name + i);
557 {
558 FRAG_APPEND_1_CHAR (ch);
559 }
560 }
561 frag_align (2, 0);
562
563 subseg_set (seg, subseg);
564 }
565 else
566 {
567 as_bad ("Expected quoted string");
568 }
569 demand_empty_rest_of_line ();
570 }
571
572 static void
573 obj_elf_size (ignore)
574 int ignore;
575 {
576 char *name = input_line_pointer;
577 char c = get_symbol_end ();
578 char *p;
579 expressionS exp;
580 symbolS *sym;
581
582 p = input_line_pointer;
583 *p = c;
584 SKIP_WHITESPACE ();
585 if (*input_line_pointer != ',')
586 {
587 *p = 0;
588 as_bad ("expected comma after name `%s' in .size directive", name);
589 *p = c;
590 ignore_rest_of_line ();
591 return;
592 }
593 input_line_pointer++;
594 expression (&exp);
595 if (exp.X_op == O_absent)
596 {
597 as_bad ("missing expression in .size directive");
598 exp.X_op = O_constant;
599 exp.X_add_number = 0;
600 }
601 *p = 0;
602 sym = symbol_find_or_make (name);
603 *p = c;
604 if (exp.X_op == O_constant)
605 S_SET_SIZE (sym, exp.X_add_number);
606 else
607 {
608 #if 0
609 static int warned;
610 if (!warned)
611 {
612 as_tsktsk (".size expressions not yet supported, ignored");
613 warned++;
614 }
615 #endif
616 }
617 demand_empty_rest_of_line ();
618 }
619
620 static void
621 obj_elf_type (ignore)
622 int ignore;
623 {
624 char *name = input_line_pointer;
625 char c = get_symbol_end ();
626 char *p;
627 int type = 0;
628 symbolS *sym;
629
630 p = input_line_pointer;
631 *p = c;
632 SKIP_WHITESPACE ();
633 if (*input_line_pointer != ',')
634 {
635 as_bad ("expected comma after name in .type directive");
636 egress:
637 ignore_rest_of_line ();
638 return;
639 }
640 input_line_pointer++;
641 SKIP_WHITESPACE ();
642 if (*input_line_pointer != '#' && *input_line_pointer != '@')
643 {
644 as_bad ("expected `#' or `@' after comma in .type directive");
645 goto egress;
646 }
647 input_line_pointer++;
648 if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1))
649 {
650 type = BSF_FUNCTION;
651 input_line_pointer += sizeof ("function") - 1;
652 }
653 else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1))
654 {
655 input_line_pointer += sizeof ("object") - 1;
656 }
657 else
658 {
659 as_bad ("unrecognized symbol type, ignored");
660 goto egress;
661 }
662 demand_empty_rest_of_line ();
663 *p = 0;
664 sym = symbol_find_or_make (name);
665 sym->bsym->flags |= type;
666 }
667
668 static void
669 obj_elf_ident (ignore)
670 int ignore;
671 {
672 static segT comment_section;
673 segT old_section = now_seg;
674 int old_subsection = now_subseg;
675
676 if (!comment_section)
677 {
678 char *p;
679 comment_section = subseg_new (".comment", 0);
680 bfd_set_section_flags (stdoutput, comment_section, SEC_HAS_CONTENTS);
681 p = frag_more (1);
682 *p = 0;
683 }
684 else
685 subseg_set (comment_section, 0);
686 stringer (1);
687 subseg_set (old_section, old_subsection);
688 }
689
690 static void
691 adjust_stab_sections (abfd, sec, xxx)
692 bfd *abfd;
693 asection *sec;
694 PTR xxx;
695 {
696 char *name;
697 asection *strsec;
698 char *p;
699 int strsz, nsyms;
700
701 if (strncmp (".stab", sec->name, 5))
702 return;
703 if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
704 return;
705
706 name = (char *) alloca (strlen (sec->name) + 4);
707 strcpy (name, sec->name);
708 strcat (name, "str");
709 strsec = bfd_get_section_by_name (abfd, name);
710 if (strsec)
711 strsz = bfd_section_size (abfd, strsec);
712 else
713 strsz = 0;
714 nsyms = bfd_section_size (abfd, sec) / 12 - 1;
715
716 p = seg_info (sec)->stabu.p;
717 assert (p != 0);
718
719 bfd_h_put_16 (abfd, (bfd_vma) nsyms, p + 6);
720 bfd_h_put_32 (abfd, (bfd_vma) strsz, p + 8);
721 }
722
723 void
724 elf_frob_file ()
725 {
726 bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
727
728 #ifdef elf_tc_symbol
729 {
730 int i;
731
732 for (i = 0; i < stdoutput->symcount; i++)
733 elf_tc_symbol (stdoutput, (PTR) (stdoutput->outsymbols[i]),
734 i + 1);
735 }
736 #endif
737
738 #ifdef elf_tc_final_processing
739 elf_tc_final_processing ();
740 #endif
741
742 /* Finally, we must make any target-specific sections. */
743
744 #ifdef elf_tc_make_sections
745 elf_tc_make_sections (stdoutput);
746 #endif
747 }
This page took 0.05657 seconds and 5 git commands to generate.