Smuggle N_WARNING symbols into BFD in obj_aout_frob_symbol.
[external/binutils.git] / gas / config / obj-aout.c
1 /* a.out object file format
2    Copyright (C) 1989, 1990, 1991 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 #ifdef BFD_ASSEMBLER
22 #include "aout/aout64.h"
23 #endif
24 #include "obstack.h"
25
26 #ifndef BFD_ASSEMBLER
27 /* in: segT   out: N_TYPE bits */
28 const short seg_N_TYPE[] =
29 {
30   N_ABS,
31   N_TEXT,
32   N_DATA,
33   N_BSS,
34   N_UNDF,                       /* unknown */
35   N_UNDF,                       /* error */
36   N_UNDF,                       /* expression */
37   N_UNDF,                       /* debug */
38   N_UNDF,                       /* ntv */
39   N_UNDF,                       /* ptv */
40   N_REGISTER,                   /* register */
41 };
42
43 const segT N_TYPE_seg[N_TYPE + 2] =
44 {                               /* N_TYPE == 0x1E = 32-2 */
45   SEG_UNKNOWN,                  /* N_UNDF == 0 */
46   SEG_GOOF,
47   SEG_ABSOLUTE,                 /* N_ABS == 2 */
48   SEG_GOOF,
49   SEG_TEXT,                     /* N_TEXT == 4 */
50   SEG_GOOF,
51   SEG_DATA,                     /* N_DATA == 6 */
52   SEG_GOOF,
53   SEG_BSS,                      /* N_BSS == 8 */
54   SEG_GOOF,
55   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
56   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
57   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
58   SEG_REGISTER,                 /* dummy N_REGISTER for regs = 30 */
59   SEG_GOOF,
60 };
61 #endif
62
63 static void obj_aout_line PARAMS ((int));
64
65 const pseudo_typeS obj_pseudo_table[] =
66 {
67   {"line", obj_aout_line, 0},   /* source code line number */
68   {"ln", obj_aout_line, 0},     /* coff line number that we use anyway */
69
70   /* coff debug pseudos (ignored) */
71   {"def", s_ignore, 0},
72   {"dim", s_ignore, 0},
73   {"endef", s_ignore, 0},
74   {"ident", s_ignore, 0},
75   {"line", s_ignore, 0},
76   {"ln", s_ignore, 0},
77   {"scl", s_ignore, 0},
78   {"size", s_ignore, 0},
79   {"tag", s_ignore, 0},
80   {"type", s_ignore, 0},
81   {"val", s_ignore, 0},
82   {"version", s_ignore, 0},
83
84   {"optim", s_ignore, 0},       /* For sun386i cc (?) */
85
86   /* other stuff */
87   {"ABORT", s_abort, 0},
88
89   {NULL}                        /* end sentinel */
90 };                              /* obj_pseudo_table */
91
92
93 #ifdef BFD_ASSEMBLER
94
95 void
96 obj_aout_frob_symbol (sym, punt)
97      symbolS *sym;
98      int *punt;
99 {
100   flagword flags;
101   asection *sec;
102   int desc, type, other;
103
104   flags = sym->bsym->flags;
105   desc = S_GET_DESC (sym);
106   type = S_GET_TYPE (sym);
107   other = S_GET_OTHER (sym);
108   sec = sym->bsym->section;
109
110   /* Only frob simple symbols this way right now.  */
111   if (! (type & ~ (N_TYPE | N_EXT)))
112     {
113       if (type == (N_UNDF | N_EXT)
114           && sec == &bfd_abs_section)
115         sym->bsym->section = sec = &bfd_und_section;
116
117       if ((type & N_TYPE) != N_INDR
118           && type != N_WARNING
119           && (sec == &bfd_abs_section
120               || sec == &bfd_und_section))
121         return;
122       if (flags & BSF_EXPORT)
123         type |= N_EXT;
124
125       switch (type & N_TYPE)
126         {
127         case N_SETA:
128         case N_SETT:
129         case N_SETD:
130         case N_SETB:
131           /* Set the debugging flag for constructor symbols so that
132              BFD leaves them alone.  */
133           sym->bsym->flags |= BSF_DEBUGGING;
134           break;
135         case N_INDR:
136           /* Put indirect symbols in the indirect section.  */
137           sym->bsym->section = &bfd_ind_section;
138           sym->bsym->flags |= BSF_INDIRECT;
139           break;
140         case N_WARNING:
141           /* Mark warning symbols.  */
142           sym->bsym->flags |= BSF_WARNING;
143           break;
144         }
145     }
146   else
147     {
148       sym->bsym->flags |= BSF_DEBUGGING;
149     }
150
151   S_SET_TYPE (sym, type);
152 }
153
154 #else
155
156 /* Relocation. */
157
158 /*
159  *              emit_relocations()
160  *
161  * Crawl along a fixS chain. Emit the segment's relocations.
162  */
163 void
164 obj_emit_relocations (where, fixP, segment_address_in_file)
165      char **where;
166      fixS *fixP;                /* Fixup chain for this segment. */
167      relax_addressT segment_address_in_file;
168 {
169   for (; fixP; fixP = fixP->fx_next)
170     if (fixP->fx_addsy != NULL)
171       {
172         tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
173         *where += md_reloc_size;
174       }
175 }
176
177 #ifndef obj_header_append
178 /* Aout file generation & utilities */
179 void
180 obj_header_append (where, headers)
181      char **where;
182      object_headers *headers;
183 {
184   tc_headers_hook (headers);
185
186 #ifdef CROSS_COMPILE
187   md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info));
188   *where += sizeof (headers->header.a_info);
189   md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
190   *where += sizeof (headers->header.a_text);
191   md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
192   *where += sizeof (headers->header.a_data);
193   md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
194   *where += sizeof (headers->header.a_bss);
195   md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
196   *where += sizeof (headers->header.a_syms);
197   md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
198   *where += sizeof (headers->header.a_entry);
199   md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
200   *where += sizeof (headers->header.a_trsize);
201   md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
202   *where += sizeof (headers->header.a_drsize);
203
204 #else /* CROSS_COMPILE */
205
206   append (where, (char *) &headers->header, sizeof (headers->header));
207 #endif /* CROSS_COMPILE */
208
209 }
210 #endif
211
212 void
213 obj_symbol_to_chars (where, symbolP)
214      char **where;
215      symbolS *symbolP;
216 {
217   md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP)));
218   md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP)));
219   md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value));
220
221   append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
222 }
223
224 void
225 obj_emit_symbols (where, symbol_rootP)
226      char **where;
227      symbolS *symbol_rootP;
228 {
229   symbolS *symbolP;
230
231   /* Emit all symbols left in the symbol chain.  */
232   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
233     {
234       /* Used to save the offset of the name. It is used to point
235          to the string in memory but must be a file offset. */
236       register char *temp;
237
238       temp = S_GET_NAME (symbolP);
239       S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
240
241       /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
242       if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
243         S_SET_EXTERNAL (symbolP);
244
245       obj_symbol_to_chars (where, symbolP);
246       S_SET_NAME (symbolP, temp);
247     }
248 }
249
250 #endif /* ! BFD_ASSEMBLER */
251
252 static void
253 obj_aout_line (ignore)
254      int ignore;
255 {
256   /* Assume delimiter is part of expression.
257      BSD4.2 as fails with delightful bug, so we
258      are not being incompatible here. */
259   new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
260   demand_empty_rest_of_line ();
261 }                               /* obj_aout_line() */
262
263 void
264 obj_read_begin_hook ()
265 {
266 }
267
268 #ifndef BFD_ASSEMBLER
269
270 void
271 obj_crawl_symbol_chain (headers)
272      object_headers *headers;
273 {
274   symbolS *symbolP;
275   symbolS **symbolPP;
276   int symbol_number = 0;
277
278   tc_crawl_symbol_chain (headers);
279
280   symbolPP = &symbol_rootP;     /*->last symbol chain link. */
281   while ((symbolP = *symbolPP) != NULL)
282     {
283       if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_DATA))
284         {
285           S_SET_SEGMENT (symbolP, SEG_TEXT);
286         }                       /* if pusing data into text */
287
288       resolve_symbol_value (symbolP);
289
290       /* OK, here is how we decide which symbols go out into the brave
291          new symtab.  Symbols that do are:
292
293          * symbols with no name (stabd's?)
294          * symbols with debug info in their N_TYPE
295
296          Symbols that don't are:
297          * symbols that are registers
298          * symbols with \1 as their 3rd character (numeric labels)
299          * "local labels" as defined by S_LOCAL_NAME(name) if the -L
300          switch was passed to gas.
301
302          All other symbols are output.  We complain if a deleted
303          symbol was marked external. */
304
305
306       if (!S_IS_REGISTER (symbolP)
307           && (!S_GET_NAME (symbolP)
308               || S_IS_DEBUG (symbolP)
309 #ifdef TC_I960
310       /* FIXME-SOON this ifdef seems highly dubious to me.  xoxorich. */
311               || !S_IS_DEFINED (symbolP)
312               || S_IS_EXTERNAL (symbolP)
313 #endif /* TC_I960 */
314               || (S_GET_NAME (symbolP)[0] != '\001' && (flagseen['L'] || !S_LOCAL_NAME (symbolP)))))
315         {
316           symbolP->sy_number = symbol_number++;
317
318           /* The + 1 after strlen account for the \0 at the
319                            end of each string */
320           if (!S_IS_STABD (symbolP))
321             {
322               /* Ordinary case. */
323               symbolP->sy_name_offset = string_byte_count;
324               string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
325             }
326           else                  /* .Stabd case. */
327             symbolP->sy_name_offset = 0;
328           symbolPP = &(symbol_next (symbolP));
329         }
330       else
331         {
332           if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
333             {
334               as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP)));
335             }                   /* oops. */
336
337           /* Unhook it from the chain */
338           *symbolPP = symbol_next (symbolP);
339         }                       /* if this symbol should be in the output */
340     }                           /* for each symbol */
341
342   H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
343 }
344
345 /*
346  * Find strings by crawling along symbol table chain.
347  */
348
349 void
350 obj_emit_strings (where)
351      char **where;
352 {
353   symbolS *symbolP;
354
355 #ifdef CROSS_COMPILE
356   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
357   md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
358   *where += sizeof (string_byte_count);
359 #else /* CROSS_COMPILE */
360   append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count));
361 #endif /* CROSS_COMPILE */
362
363   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
364     {
365       if (S_GET_NAME (symbolP))
366         append (&next_object_file_charP, S_GET_NAME (symbolP),
367                 (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
368     }                           /* walk symbol chain */
369 }
370
371 #ifndef AOUT_VERSION
372 #define AOUT_VERSION 0
373 #endif
374
375 void
376 obj_pre_write_hook (headers)
377      object_headers *headers;
378 {
379   H_SET_DYNAMIC (headers, 0);
380   H_SET_VERSION (headers, AOUT_VERSION);
381   H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
382   tc_aout_pre_write_hook (headers);
383 }
384
385 void
386 DEFUN_VOID (s_sect)
387 {
388   /* Strip out the section name */
389   char *section_name;
390   char *section_name_end;
391   char c;
392
393   unsigned int len;
394   unsigned int exp;
395   char *save;
396
397   section_name = input_line_pointer;
398   c = get_symbol_end ();
399   section_name_end = input_line_pointer;
400
401   len = section_name_end - section_name;
402   input_line_pointer++;
403   save = input_line_pointer;
404
405   SKIP_WHITESPACE ();
406   if (c == ',')
407     {
408       exp = get_absolute_expression ();
409     }
410   else if (*input_line_pointer == ',')
411     {
412       input_line_pointer++;
413       exp = get_absolute_expression ();
414     }
415   else
416     {
417       input_line_pointer = save;
418       exp = 0;
419     }
420   if (exp >= 1000)
421     {
422       as_bad ("subsegment index too high");
423     }
424
425   if (strcmp (section_name, ".text") == 0)
426     {
427       subseg_set (SEG_TEXT, (subsegT) exp);
428     }
429
430   if (strcmp (section_name, ".data") == 0)
431     {
432       if (flagseen['R'])
433         subseg_set (SEG_TEXT, (subsegT) exp + 1000);
434       else
435         subseg_set (SEG_DATA, (subsegT) exp);
436     }
437
438   *section_name_end = c;
439 }
440
441 #endif /* ! BFD_ASSEMBLER */
442
443 /* end of obj-aout.c */