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