* configure.in (AC_C_BIGENDIAN): Invoke.
[external/binutils.git] / gas / config / obj-aout.c
1 /* a.out object file format
2    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
3    2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2,
10 or (at your option) any later version.
11
12 GAS is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15 the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 #define OBJ_HEADER "obj-aout.h"
23
24 #include "as.h"
25 #ifdef BFD_ASSEMBLER
26 #undef NO_RELOC
27 #include "aout/aout64.h"
28 #endif
29 #include "obstack.h"
30
31 #ifndef BFD_ASSEMBLER
32 /* in: segT   out: N_TYPE bits */
33 const short seg_N_TYPE[] =
34 {
35   N_ABS,
36   N_TEXT,
37   N_DATA,
38   N_BSS,
39   N_UNDF,                       /* unknown */
40   N_UNDF,                       /* error */
41   N_UNDF,                       /* expression */
42   N_UNDF,                       /* debug */
43   N_UNDF,                       /* ntv */
44   N_UNDF,                       /* ptv */
45   N_REGISTER,                   /* register */
46 };
47
48 const segT N_TYPE_seg[N_TYPE + 2] =
49 {                               /* N_TYPE == 0x1E = 32-2 */
50   SEG_UNKNOWN,                  /* N_UNDF == 0 */
51   SEG_GOOF,
52   SEG_ABSOLUTE,                 /* N_ABS == 2 */
53   SEG_GOOF,
54   SEG_TEXT,                     /* N_TEXT == 4 */
55   SEG_GOOF,
56   SEG_DATA,                     /* N_DATA == 6 */
57   SEG_GOOF,
58   SEG_BSS,                      /* N_BSS == 8 */
59   SEG_GOOF,
60   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
61   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
62   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
63   SEG_REGISTER,                 /* dummy N_REGISTER for regs = 30 */
64   SEG_GOOF,
65 };
66 #endif
67
68 static void obj_aout_line PARAMS ((int));
69 static void obj_aout_weak PARAMS ((int));
70 static void obj_aout_type PARAMS ((int));
71
72 const pseudo_typeS aout_pseudo_table[] =
73 {
74   {"line", obj_aout_line, 0},   /* source code line number */
75   {"ln", obj_aout_line, 0},     /* coff line number that we use anyway */
76
77   {"weak", obj_aout_weak, 0},   /* mark symbol as weak.  */
78
79   {"type", obj_aout_type, 0},
80
81   /* coff debug pseudos (ignored) */
82   {"def", s_ignore, 0},
83   {"dim", s_ignore, 0},
84   {"endef", s_ignore, 0},
85   {"ident", s_ignore, 0},
86   {"line", s_ignore, 0},
87   {"ln", s_ignore, 0},
88   {"scl", s_ignore, 0},
89   {"size", s_ignore, 0},
90   {"tag", s_ignore, 0},
91   {"val", s_ignore, 0},
92   {"version", s_ignore, 0},
93
94   {"optim", s_ignore, 0},       /* For sun386i cc (?) */
95
96   /* other stuff */
97   {"ABORT", s_abort, 0},
98
99   {NULL, NULL, 0}               /* end sentinel */
100 };                              /* aout_pseudo_table */
101
102 #ifdef BFD_ASSEMBLER
103
104 void
105 obj_aout_frob_symbol (sym, punt)
106      symbolS *sym;
107      int *punt ATTRIBUTE_UNUSED;
108 {
109   flagword flags;
110   asection *sec;
111   int desc, type, other;
112
113   flags = symbol_get_bfdsym (sym)->flags;
114   desc = aout_symbol (symbol_get_bfdsym (sym))->desc;
115   type = aout_symbol (symbol_get_bfdsym (sym))->type;
116   other = aout_symbol (symbol_get_bfdsym (sym))->other;
117   sec = S_GET_SEGMENT (sym);
118
119   /* Only frob simple symbols this way right now.  */
120   if (! (type & ~ (N_TYPE | N_EXT)))
121     {
122       if (type == (N_UNDF | N_EXT)
123           && sec == &bfd_abs_section)
124         {
125           sec = bfd_und_section_ptr;
126           S_SET_SEGMENT (sym, sec);
127         }
128
129       if ((type & N_TYPE) != N_INDR
130           && (type & N_TYPE) != N_SETA
131           && (type & N_TYPE) != N_SETT
132           && (type & N_TYPE) != N_SETD
133           && (type & N_TYPE) != N_SETB
134           && type != N_WARNING
135           && (sec == &bfd_abs_section
136               || sec == &bfd_und_section))
137         return;
138       if (flags & BSF_EXPORT)
139         type |= N_EXT;
140
141       switch (type & N_TYPE)
142         {
143         case N_SETA:
144         case N_SETT:
145         case N_SETD:
146         case N_SETB:
147           /* Set the debugging flag for constructor symbols so that
148              BFD leaves them alone.  */
149           symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
150
151           /* You can't put a common symbol in a set.  The way a set
152              element works is that the symbol has a definition and a
153              name, and the linker adds the definition to the set of
154              that name.  That does not work for a common symbol,
155              because the linker can't tell which common symbol the
156              user means.  FIXME: Using as_bad here may be
157              inappropriate, since the user may want to force a
158              particular type without regard to the semantics of sets;
159              on the other hand, we certainly don't want anybody to be
160              mislead into thinking that their code will work.  */
161           if (S_IS_COMMON (sym))
162             as_bad (_("Attempt to put a common symbol into set %s"),
163                     S_GET_NAME (sym));
164           /* Similarly, you can't put an undefined symbol in a set.  */
165           else if (! S_IS_DEFINED (sym))
166             as_bad (_("Attempt to put an undefined symbol into set %s"),
167                     S_GET_NAME (sym));
168
169           break;
170         case N_INDR:
171           /* Put indirect symbols in the indirect section.  */
172           S_SET_SEGMENT (sym, bfd_ind_section_ptr);
173           symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
174           if (type & N_EXT)
175             {
176               symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
177               symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
178             }
179           break;
180         case N_WARNING:
181           /* Mark warning symbols.  */
182           symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
183           break;
184         }
185     }
186   else
187     {
188       symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
189     }
190
191   aout_symbol (symbol_get_bfdsym (sym))->type = type;
192
193   /* Double check weak symbols.  */
194   if (S_IS_WEAK (sym))
195     {
196       if (S_IS_COMMON (sym))
197         as_bad (_("Symbol `%s' can not be both weak and common"),
198                 S_GET_NAME (sym));
199     }
200 }
201
202 void
203 obj_aout_frob_file_before_fix ()
204 {
205   /* Relocation processing may require knowing the VMAs of the sections.
206      Since writing to a section will cause the BFD back end to compute the
207      VMAs, fake it out here....  */
208   bfd_byte b = 0;
209   bfd_boolean x = TRUE;
210   if (bfd_section_size (stdoutput, text_section) != 0)
211     {
212       x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
213                                     (bfd_size_type) 1);
214     }
215   else if (bfd_section_size (stdoutput, data_section) != 0)
216     {
217       x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
218                                     (bfd_size_type) 1);
219     }
220   assert (x);
221 }
222
223 #else /* ! BFD_ASSEMBLER */
224
225 /* Relocation.  */
226
227 /*
228  *              emit_relocations()
229  *
230  * Crawl along a fixS chain. Emit the segment's relocations.
231  */
232 void
233 obj_emit_relocations (where, fixP, segment_address_in_file)
234      char **where;
235      fixS *fixP;                /* Fixup chain for this segment.  */
236      relax_addressT segment_address_in_file;
237 {
238   for (; fixP; fixP = fixP->fx_next)
239     if (fixP->fx_done == 0)
240       {
241         symbolS *sym;
242
243         sym = fixP->fx_addsy;
244         while (sym->sy_value.X_op == O_symbol
245                && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
246           sym = sym->sy_value.X_add_symbol;
247         fixP->fx_addsy = sym;
248
249         if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
250           {
251             char *file;
252             unsigned int line;
253
254             if (expr_symbol_where (sym, &file, &line))
255               as_bad_where (file, line, _("unresolved relocation"));
256             else
257               as_bad (_("bad relocation: symbol `%s' not in symbol table"),
258                       S_GET_NAME (sym));
259           }
260
261         tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
262         *where += md_reloc_size;
263       }
264 }
265
266 #ifndef obj_header_append
267 /* Aout file generation & utilities */
268
269 /* An AOUT header on disk is laid out in target byte order.  */
270
271 void
272 obj_header_append (where, headers)
273      char **where;
274      object_headers *headers;
275 {
276   char *p;
277
278   tc_headers_hook (headers);
279
280 #ifdef __A_OUT_GNU_H__
281 #define SIZEOF_HEADER(PIECE) (sizeof (((struct exec_bytes *) 0)->PIECE))
282 #else
283 #define SIZEOF_HEADER(PIECE) 4
284 #endif
285 #define DO(PIECE) \
286   md_number_to_chars (p, headers->header.PIECE, SIZEOF_HEADER (PIECE)); \
287   p += SIZEOF_HEADER (PIECE);
288
289   p = *where;
290   DO (a_info);
291   DO (a_text);
292   DO (a_data);
293   DO (a_bss);
294   DO (a_syms);
295   DO (a_entry);
296   DO (a_trsize);
297   DO (a_drsize);
298   *where = p;
299 #undef DO
300 #undef SIZEOF_HEADER
301 }
302 #endif /* ! defined (obj_header_append) */
303
304 void
305 obj_symbol_to_chars (where, symbolP)
306      char **where;
307      symbolS *symbolP;
308 {
309   char *p = *where;
310   md_number_to_chars (p, S_GET_OFFSET (symbolP), 4);
311   p += 4;
312   /* Can't use S_GET_TYPE here as it masks.  */
313   *p++ = symbolP->sy_symbol.n_type;
314   *p++ = symbolP->sy_symbol.n_other;
315   md_number_to_chars (p, S_GET_DESC (symbolP), 2);
316   p += 2;
317   md_number_to_chars (p, S_GET_VALUE (symbolP), 4);
318   p += 4;
319   *where = p;
320 }
321
322 void
323 obj_emit_symbols (where, symbol_rootP)
324      char **where;
325      symbolS *symbol_rootP;
326 {
327   symbolS *symbolP;
328
329   /* Emit all symbols left in the symbol chain.  */
330   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
331     {
332       /* Used to save the offset of the name. It is used to point
333          to the string in memory but must be a file offset.  */
334       register char *temp;
335
336       temp = S_GET_NAME (symbolP);
337       S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
338
339       /* Any symbol still undefined and is not a dbg symbol is made N_EXT.  */
340       if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
341         S_SET_EXTERNAL (symbolP);
342
343       /* Adjust the type of a weak symbol.  */
344       if (S_GET_WEAK (symbolP))
345         {
346           switch (S_GET_TYPE (symbolP))
347             {
348             case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
349             case N_ABS:  S_SET_TYPE (symbolP, N_WEAKA); break;
350             case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
351             case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
352             case N_BSS:  S_SET_TYPE (symbolP, N_WEAKB); break;
353             default: as_bad (_("%s: bad type for weak symbol"), temp); break;
354             }
355         }
356
357       obj_symbol_to_chars (where, symbolP);
358       S_SET_NAME (symbolP, temp);
359     }
360 }
361
362 #endif /* ! BFD_ASSEMBLER */
363
364 static void
365 obj_aout_line (ignore)
366      int ignore ATTRIBUTE_UNUSED;
367 {
368   /* Assume delimiter is part of expression.
369      BSD4.2 as fails with delightful bug, so we
370      are not being incompatible here.  */
371   new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
372   demand_empty_rest_of_line ();
373 }                               /* obj_aout_line() */
374
375 /* Handle .weak.  This is a GNU extension.  */
376
377 static void
378 obj_aout_weak (ignore)
379      int ignore ATTRIBUTE_UNUSED;
380 {
381   char *name;
382   int c;
383   symbolS *symbolP;
384
385   do
386     {
387       name = input_line_pointer;
388       c = get_symbol_end ();
389       symbolP = symbol_find_or_make (name);
390       *input_line_pointer = c;
391       SKIP_WHITESPACE ();
392       S_SET_WEAK (symbolP);
393       if (c == ',')
394         {
395           input_line_pointer++;
396           SKIP_WHITESPACE ();
397           if (*input_line_pointer == '\n')
398             c = '\n';
399         }
400     }
401   while (c == ',');
402   demand_empty_rest_of_line ();
403 }
404
405 /* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
406    which is then apparently used when doing dynamic linking.  Older
407    versions of gas ignored the .type pseudo-op, so we also ignore it if
408    we can't parse it.  */
409
410 static void
411 obj_aout_type (ignore)
412      int ignore ATTRIBUTE_UNUSED;
413 {
414   char *name;
415   int c;
416   symbolS *sym;
417
418   name = input_line_pointer;
419   c = get_symbol_end ();
420   sym = symbol_find_or_make (name);
421   *input_line_pointer = c;
422   SKIP_WHITESPACE ();
423   if (*input_line_pointer == ',')
424     {
425       ++input_line_pointer;
426       SKIP_WHITESPACE ();
427       if (*input_line_pointer == '@')
428         {
429           ++input_line_pointer;
430           if (strncmp (input_line_pointer, "object", 6) == 0)
431             S_SET_OTHER (sym, 1);
432           else if (strncmp (input_line_pointer, "function", 8) == 0)
433             S_SET_OTHER (sym, 2);
434         }
435     }
436
437   /* Ignore everything else on the line.  */
438   s_ignore (0);
439 }
440
441 #ifndef BFD_ASSEMBLER
442
443 void
444 obj_crawl_symbol_chain (headers)
445      object_headers *headers;
446 {
447   symbolS *symbolP;
448   symbolS **symbolPP;
449   int symbol_number = 0;
450
451   tc_crawl_symbol_chain (headers);
452
453   symbolPP = &symbol_rootP;     /*->last symbol chain link.  */
454   while ((symbolP = *symbolPP) != NULL)
455     {
456       if (symbolP->sy_mri_common)
457         {
458           if (S_IS_EXTERNAL (symbolP))
459             as_bad (_("%s: global symbols not supported in common sections"),
460                     S_GET_NAME (symbolP));
461           *symbolPP = symbol_next (symbolP);
462           continue;
463         }
464
465       if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
466         {
467           S_SET_SEGMENT (symbolP, SEG_TEXT);
468         }                       /* if pushing data into text */
469
470       resolve_symbol_value (symbolP);
471
472       /* Skip symbols which were equated to undefined or common
473          symbols.  Also skip defined uncommon symbols which can
474          be resolved since in this case they should have been
475          resolved to a non-symbolic constant.  */
476       if (symbolP->sy_value.X_op == O_symbol
477           && (! S_IS_DEFINED (symbolP)
478               || S_IS_COMMON (symbolP)
479               || symbol_resolved_p (symbolP)))
480         {
481           *symbolPP = symbol_next (symbolP);
482           continue;
483         }
484
485       /* OK, here is how we decide which symbols go out into the brave
486          new symtab.  Symbols that do are:
487
488          * symbols with no name (stabd's?)
489          * symbols with debug info in their N_TYPE
490
491          Symbols that don't are:
492          * symbols that are registers
493          * symbols with \1 as their 3rd character (numeric labels)
494          * "local labels" as defined by S_LOCAL_NAME(name) if the -L
495          switch was passed to gas.
496
497          All other symbols are output.  We complain if a deleted
498          symbol was marked external.  */
499
500       if (!S_IS_REGISTER (symbolP)
501           && (!S_GET_NAME (symbolP)
502               || S_IS_DEBUG (symbolP)
503               || !S_IS_DEFINED (symbolP)
504               || S_IS_EXTERNAL (symbolP)
505               || (S_GET_NAME (symbolP)[0] != '\001'
506                   && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
507         {
508           symbolP->sy_number = symbol_number++;
509
510           /* The + 1 after strlen account for the \0 at the
511                            end of each string */
512           if (!S_IS_STABD (symbolP))
513             {
514               /* Ordinary case.  */
515               symbolP->sy_name_offset = string_byte_count;
516               string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
517             }
518           else                  /* .Stabd case.  */
519             symbolP->sy_name_offset = 0;
520           symbolPP = &symbolP->sy_next;
521         }
522       else
523         {
524           if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
525             /* This warning should never get triggered any more.
526                Well, maybe if you're doing twisted things with
527                register names...  */
528             {
529               as_bad (_("Local symbol %s never defined."), decode_local_label_name (S_GET_NAME (symbolP)));
530             }                   /* oops.  */
531
532           /* Unhook it from the chain */
533           *symbolPP = symbol_next (symbolP);
534         }                       /* if this symbol should be in the output */
535     }                           /* for each symbol */
536
537   H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
538 }
539
540 /*
541  * Find strings by crawling along symbol table chain.
542  */
543
544 void
545 obj_emit_strings (where)
546      char **where;
547 {
548   symbolS *symbolP;
549
550   md_number_to_chars (*where, string_byte_count, 4);
551   *where += 4;
552
553   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
554     {
555       if (S_GET_NAME (symbolP))
556         append (where, S_GET_NAME (symbolP),
557                 (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
558     }                           /* walk symbol chain */
559 }
560
561 #ifndef AOUT_VERSION
562 #define AOUT_VERSION 0
563 #endif
564
565 void
566 obj_pre_write_hook (headers)
567      object_headers *headers;
568 {
569   H_SET_DYNAMIC (headers, 0);
570   H_SET_VERSION (headers, AOUT_VERSION);
571   H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
572   tc_aout_pre_write_hook (headers);
573 }
574
575 #endif /* ! BFD_ASSEMBLER */
576
577 #ifdef BFD_ASSEMBLER
578
579 /* Support for an AOUT emulation.  */
580
581 static void aout_pop_insert PARAMS ((void));
582 static int obj_aout_s_get_other PARAMS ((symbolS *));
583 static void obj_aout_s_set_other PARAMS ((symbolS *, int));
584 static int obj_aout_s_get_desc PARAMS ((symbolS *));
585 static void obj_aout_s_set_desc PARAMS ((symbolS *, int));
586 static int obj_aout_s_get_type PARAMS ((symbolS *));
587 static void obj_aout_s_set_type PARAMS ((symbolS *, int));
588 static int obj_aout_separate_stab_sections PARAMS ((void));
589 static int obj_aout_sec_sym_ok_for_reloc PARAMS ((asection *));
590 static void obj_aout_process_stab PARAMS ((segT, int, const char *, int, int, int));
591
592 static void
593 aout_pop_insert ()
594 {
595   pop_insert (aout_pseudo_table);
596 }
597
598 static int
599 obj_aout_s_get_other (sym)
600      symbolS *sym;
601 {
602   return aout_symbol (symbol_get_bfdsym (sym))->other;
603 }
604
605 static void
606 obj_aout_s_set_other (sym, o)
607      symbolS *sym;
608      int o;
609 {
610   aout_symbol (symbol_get_bfdsym (sym))->other = o;
611 }
612
613 static int
614 obj_aout_sec_sym_ok_for_reloc (sec)
615      asection *sec ATTRIBUTE_UNUSED;
616 {
617   return obj_sec_sym_ok_for_reloc (sec);
618 }
619
620 static void
621 obj_aout_process_stab (seg, w, s, t, o, d)
622      segT seg ATTRIBUTE_UNUSED;
623      int w;
624      const char *s;
625      int t;
626      int o;
627      int d;
628 {
629   aout_process_stab (w, s, t, o, d);
630 }
631
632 static int
633 obj_aout_s_get_desc (sym)
634      symbolS *sym;
635 {
636   return aout_symbol (symbol_get_bfdsym (sym))->desc;
637 }
638
639 static void
640 obj_aout_s_set_desc (sym, d)
641      symbolS *sym;
642      int d;
643 {
644   aout_symbol (symbol_get_bfdsym (sym))->desc = d;
645 }
646
647 static int
648 obj_aout_s_get_type (sym)
649      symbolS *sym;
650 {
651   return aout_symbol (symbol_get_bfdsym (sym))->type;
652 }
653
654 static void
655 obj_aout_s_set_type (sym, t)
656      symbolS *sym;
657      int t;
658 {
659   aout_symbol (symbol_get_bfdsym (sym))->type = t;
660 }
661
662 static int
663 obj_aout_separate_stab_sections ()
664 {
665   return 0;
666 }
667
668 /* When changed, make sure these table entries match the single-format
669    definitions in obj-aout.h.  */
670 const struct format_ops aout_format_ops =
671 {
672   bfd_target_aout_flavour,
673   1,    /* dfl_leading_underscore */
674   0,    /* emit_section_symbols */
675   0,    /* begin */
676   0,    /* app_file */
677   obj_aout_frob_symbol,
678   0,    /* frob_file */
679   0,    /* frob_file_before_adjust */
680   obj_aout_frob_file_before_fix,
681   0,    /* frob_file_after_relocs */
682   0,    /* s_get_size */
683   0,    /* s_set_size */
684   0,    /* s_get_align */
685   0,    /* s_set_align */
686   obj_aout_s_get_other,
687   obj_aout_s_set_other,
688   obj_aout_s_get_desc,
689   obj_aout_s_set_desc,
690   obj_aout_s_get_type,
691   obj_aout_s_set_type,
692   0,    /* copy_symbol_attributes */
693   0,    /* generate_asm_lineno */
694   obj_aout_process_stab,
695   obj_aout_separate_stab_sections,
696   0,    /* init_stab_section */
697   obj_aout_sec_sym_ok_for_reloc,
698   aout_pop_insert,
699   0,    /* ecoff_set_ext */
700   0,    /* read_begin_hook */
701   0     /* symbol_new_hook */
702 };
703 #endif /* BFD_ASSEMBLER */