White space and comments only. The devo tree prior to this delta is
[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 #include "aout/stab_gnu.h"
22 #include "obstack.h"
23
24 /* in: segT   out: N_TYPE bits */
25 const short seg_N_TYPE[] = {
26         N_ABS,
27         N_TEXT,
28         N_DATA,
29         N_BSS,
30         N_UNDF, /* unknown */
31         N_UNDF, /* absent */
32         N_UNDF, /* pass1 */
33         N_UNDF, /* error */
34         N_UNDF, /* bignum/flonum */
35         N_UNDF, /* difference */
36         N_UNDF, /* debug */
37         N_UNDF, /* ntv */
38         N_UNDF, /* ptv */
39         N_REGISTER, /* register */
40 };
41
42 const segT N_TYPE_seg [N_TYPE+2] = {    /* N_TYPE == 0x1E = 32-2 */
43         SEG_UNKNOWN,                    /* N_UNDF == 0 */
44         SEG_GOOF,
45         SEG_ABSOLUTE,                   /* N_ABS == 2 */
46         SEG_GOOF,
47         SEG_TEXT,                       /* N_TEXT == 4 */
48         SEG_GOOF,
49         SEG_DATA,                       /* N_DATA == 6 */
50         SEG_GOOF,
51         SEG_BSS,                        /* N_BSS == 8 */
52         SEG_GOOF,
53         SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
54         SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
55         SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
56         SEG_REGISTER,                   /* dummy N_REGISTER for regs = 30 */
57         SEG_GOOF,
58 };
59
60 #ifdef __STDC__
61 static void obj_aout_stab(int what);
62 static void obj_aout_line(void);
63 static void obj_aout_desc(void);
64 #else /* __STDC__ */
65 static void obj_aout_desc();
66 static void obj_aout_stab();
67 static void obj_aout_line();
68 #endif /* __STDC__ */
69
70 const pseudo_typeS obj_pseudo_table[] = {
71 #ifndef IGNORE_DEBUG
72         /* stabs debug info */
73         { "line",       obj_aout_line,          0       }, /* source code line number */
74         { "ln",         obj_aout_line,          0       }, /* coff line number that we use anyway */
75         { "desc",       obj_aout_desc,          0       }, /* desc */
76         { "stabd",      obj_aout_stab,          'd'     }, /* stabs */
77         { "stabn",      obj_aout_stab,          'n'     }, /* stabs */
78         { "stabs",      obj_aout_stab,          's'     }, /* stabs */
79 #else /* IGNORE_DEBUG */
80         { "line",       obj_aout_line,          0       }, /* source code line number */
81         { "ln",         obj_aout_line,          0       }, /* coff line number that we use anyway */
82         { "desc",       obj_aout_desc,          0       }, /* desc */
83         { "stabd",      obj_aout_stab,          'd'     }, /* stabs */
84         { "stabn",      obj_aout_stab,          'n'     }, /* stabs */
85         { "stabs",      obj_aout_stab,          's'     }, /* stabs */
86 #endif /* IGNORE_DEBUG */
87         
88         /* coff debug pseudos (ignored) */
89         { "def",        s_ignore, 0 },
90         { "dim",        s_ignore, 0 },
91         { "endef",      s_ignore, 0 },
92         { "ident",      s_ignore, 0 },
93         { "line",       s_ignore, 0 },
94         { "ln",         s_ignore, 0 },
95         { "scl",        s_ignore, 0 },
96         { "size",       s_ignore, 0 },
97         { "tag",        s_ignore, 0 },
98         { "type",       s_ignore, 0 },
99         { "val",        s_ignore, 0 },
100         { "version",    s_ignore, 0 },
101         
102         /* stabs-in-coff (?) debug pseudos (ignored) */
103         { "optim",      s_ignore, 0 }, /* For sun386i cc (?) */
104         
105         /* other stuff */
106         { "ABORT",      s_abort,                0 },
107         
108         { NULL} /* end sentinel */
109 }; /* obj_pseudo_table */
110
111
112 /* Relocation. */
113
114 /*
115  *              emit_relocations()
116  *
117  * Crawl along a fixS chain. Emit the segment's relocations.
118  */
119 void obj_emit_relocations(where, fixP, segment_address_in_file)
120 char **where;
121 fixS *fixP; /* Fixup chain for this segment. */
122 relax_addressT segment_address_in_file;
123 {
124         for (;  fixP;  fixP = fixP->fx_next) {
125                 if (fixP->fx_addsy != NULL) {
126                         tc_aout_fix_to_chars(*where, fixP, segment_address_in_file);
127                         *where += md_reloc_size;
128                 } /* if there is an add symbol */
129         } /* for each fix */
130         
131         return;
132 } /* obj_emit_relocations() */
133
134 /* Aout file generation & utilities */
135 void obj_header_append(where, headers)
136 char **where;
137 object_headers *headers;
138 {
139         tc_headers_hook(headers);
140         
141 #ifdef CROSS_COMPILE
142         md_number_to_chars(*where, headers->header.a_info, sizeof(headers->header.a_info));
143         *where += sizeof(headers->header.a_info);
144         md_number_to_chars(*where, headers->header.a_text, sizeof(headers->header.a_text));
145         *where += sizeof(headers->header.a_text);
146         md_number_to_chars(*where, headers->header.a_data, sizeof(headers->header.a_data));
147         *where += sizeof(headers->header.a_data);
148         md_number_to_chars(*where, headers->header.a_bss, sizeof(headers->header.a_bss));
149         *where += sizeof(headers->header.a_bss);
150         md_number_to_chars(*where, headers->header.a_syms, sizeof(headers->header.a_syms));
151         *where += sizeof(headers->header.a_syms);
152         md_number_to_chars(*where, headers->header.a_entry, sizeof(headers->header.a_entry));
153         *where += sizeof(headers->header.a_entry);
154         md_number_to_chars(*where, headers->header.a_trsize, sizeof(headers->header.a_trsize));
155         *where += sizeof(headers->header.a_trsize);
156         md_number_to_chars(*where, headers->header.a_drsize, sizeof(headers->header.a_drsize));
157         *where += sizeof(headers->header.a_drsize);
158         
159 #else /* CROSS_COMPILE */
160         
161         append(where, (char *) &headers->header, sizeof(headers->header));
162 #endif /* CROSS_COMPILE */
163         
164         return;
165 } /* obj_append_header() */
166
167 void obj_symbol_to_chars(where, symbolP)
168 char **where;
169 symbolS *symbolP;
170 {
171         md_number_to_chars((char *)&(S_GET_OFFSET(symbolP)), S_GET_OFFSET(symbolP), sizeof(S_GET_OFFSET(symbolP)));
172         md_number_to_chars((char *)&(S_GET_DESC(symbolP)), S_GET_DESC(symbolP), sizeof(S_GET_DESC(symbolP)));
173         md_number_to_chars((char *)&(S_GET_VALUE(symbolP)), S_GET_VALUE(symbolP), sizeof(S_GET_VALUE(symbolP)));
174         
175         append(where, (char *)&symbolP->sy_symbol, sizeof(obj_symbol_type));
176 } /* obj_symbol_to_chars() */
177
178 void obj_emit_symbols(where, symbol_rootP)
179 char **where;
180 symbolS *symbol_rootP;
181 {
182         symbolS *       symbolP;
183         
184         /*
185          * Emit all symbols left in the symbol chain.
186          */
187         for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
188                 /* Used to save the offset of the name. It is used to point
189                    to the string in memory but must be a file offset. */
190                 register char *temp;
191                 
192                 temp = S_GET_NAME(symbolP);
193                 S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
194                 
195                 /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
196                 if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP)) S_SET_EXTERNAL(symbolP);
197                 
198                 obj_symbol_to_chars(where, symbolP);
199                 S_SET_NAME(symbolP,temp);
200         }
201 } /* emit_symbols() */
202
203 #if comment
204 /* uneeded if symbol is born zeroed. */
205 void obj_symbol_new_hook(symbolP)
206 symbolS *symbolP;
207 {
208         S_SET_OTHER(symbolP, 0);
209         S_SET_DESC(symbolP, 0);
210         return;
211 } /* obj_symbol_new_hook() */
212 #endif /* comment */
213
214 static void obj_aout_line() {
215         /* Assume delimiter is part of expression. */
216         /* BSD4.2 as fails with delightful bug, so we */
217         /* are not being incompatible here. */
218         new_logical_line((char *)NULL, (int)(get_absolute_expression()));
219         demand_empty_rest_of_line();
220 } /* obj_aout_line() */
221
222 /*
223  *                      stab()
224  *
225  * Handle .stabX directives, which used to be open-coded.
226  * So much creeping featurism overloaded the semantics that we decided
227  * to put all .stabX thinking in one place. Here.
228  *
229  * We try to make any .stabX directive legal. Other people's AS will often
230  * do assembly-time consistency checks: eg assigning meaning to n_type bits
231  * and "protecting" you from setting them to certain values. (They also zero
232  * certain bits before emitting symbols. Tut tut.)
233  *
234  * If an expression is not absolute we either gripe or use the relocation
235  * information. Other people's assemblers silently forget information they
236  * don't need and invent information they need that you didn't supply.
237  *
238  * .stabX directives always make a symbol table entry. It may be junk if
239  * the rest of your .stabX directive is malformed.
240  */
241 static void obj_aout_stab(what)
242 int what;
243 {
244         extern int listing;
245         
246         register symbolS *      symbolP = 0;
247         register char * string;
248         int saved_type = 0;
249         int length;
250         int goof; /* TRUE if we have aborted. */
251         long longint;
252         
253         /*
254          * Enter with input_line_pointer pointing past .stabX and any following
255          * whitespace.
256          */
257         goof = 0; /* JF who forgot this?? */
258         if (what == 's') {
259                 string = demand_copy_C_string(& length);
260                 SKIP_WHITESPACE();
261                 if (* input_line_pointer == ',')
262                     input_line_pointer ++;
263                 else {
264                         as_bad("I need a comma after symbol's name");
265                         goof = 1;
266                 }
267         } else
268             string = "";
269         
270         /*
271          * Input_line_pointer->after ','.  String->symbol name.
272          */
273         if (! goof) {
274                 symbolP = symbol_new(string,
275                                      SEG_UNKNOWN,
276                                      0,
277                                      (struct frag *)0);
278                 switch (what) {
279                 case 'd':
280                         S_SET_NAME(symbolP, NULL); /* .stabd feature. */
281                         S_SET_VALUE(symbolP, obstack_next_free(&frags) - frag_now->fr_literal);
282                         symbolP->sy_frag = frag_now;
283                         break;
284                         
285                 case 'n':
286                         symbolP->sy_frag = &zero_address_frag;
287                         break;
288                         
289                 case 's':
290                         symbolP->sy_frag = & zero_address_frag;
291                         break;
292                         
293                 default:
294                         BAD_CASE(what);
295                         break;
296                 }
297                 
298                 if (get_absolute_expression_and_terminator(&longint) == ',')
299                     symbolP->sy_symbol.n_type = saved_type = longint;
300                 else {
301                         as_bad("I want a comma after the n_type expression");
302                         goof = 1;
303                         input_line_pointer --; /* Backup over a non-',' char. */
304                 }
305         }
306         
307         if (!goof) {
308                 if (get_absolute_expression_and_terminator(&longint) == ',')
309                     S_SET_OTHER(symbolP, longint);
310                 else {
311                         as_bad("I want a comma after the n_other expression");
312                         goof = 1;
313                         input_line_pointer--; /* Backup over a non-',' char. */
314                 }
315         }
316         
317         if (!goof) {
318                 S_SET_DESC(symbolP, get_absolute_expression());
319                 if (what == 's' || what == 'n') {
320                         if (*input_line_pointer != ',') {
321                                 as_bad("I want a comma after the n_desc expression");
322                                 goof = 1;
323                         } else {
324                                 input_line_pointer++;
325                         }
326                 }
327         }
328         
329         if ((!goof) && (what=='s' || what=='n')) {
330                 pseudo_set(symbolP);
331                 symbolP->sy_symbol.n_type = saved_type;
332         }
333 #ifndef NO_LISTING
334         if (listing && !goof) 
335             {
336                     if (symbolP->sy_symbol.n_type == N_SLINE) 
337                         {
338                                 
339                                 listing_source_line(symbolP->sy_symbol.n_desc);
340                         }
341                     else if (symbolP->sy_symbol.n_type == N_SO
342                              || symbolP->sy_symbol.n_type == N_SOL) 
343                         {
344                                 listing_source_file(string);
345                         }                         
346             }
347 #endif  
348         
349         if (goof)
350             ignore_rest_of_line();
351         else
352             demand_empty_rest_of_line ();
353 } /* obj_aout_stab() */
354
355 static void obj_aout_desc() {
356         register char *name;
357         register char c;
358         register char *p;
359         register symbolS *symbolP;
360         register int temp;
361         
362         /*
363          * Frob invented at RMS' request. Set the n_desc of a symbol.
364          */
365         name = input_line_pointer;
366         c = get_symbol_end();
367         p = input_line_pointer;
368         * p = c;
369         SKIP_WHITESPACE();
370         if (*input_line_pointer != ',') {
371                 *p = 0;
372                 as_bad("Expected comma after name \"%s\"", name);
373                 *p = c;
374                 ignore_rest_of_line();
375         } else {
376                 input_line_pointer ++;
377                 temp = get_absolute_expression();
378                 *p = 0;
379                 symbolP = symbol_find_or_make(name);
380                 *p = c;
381                 S_SET_DESC(symbolP,temp);
382         }
383         demand_empty_rest_of_line();
384 } /* obj_aout_desc() */
385
386 void obj_read_begin_hook() {
387         return;
388 } /* obj_read_begin_hook() */
389
390 void obj_crawl_symbol_chain(headers)
391 object_headers *headers;
392 {
393         symbolS *symbolP;
394         symbolS **symbolPP;
395         int symbol_number = 0;
396         
397         /* JF deal with forward references first... */
398         for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
399                 if (symbolP->sy_forward) {
400                         S_SET_VALUE(symbolP, S_GET_VALUE(symbolP)
401                                     + S_GET_VALUE(symbolP->sy_forward)
402                                     + symbolP->sy_forward->sy_frag->fr_address);
403                         
404                         symbolP->sy_forward=0;
405                 } /* if it has a forward reference */
406         } /* walk the symbol chain */
407         
408         tc_crawl_symbol_chain(headers);
409         
410         symbolPP = &symbol_rootP;       /*->last symbol chain link. */
411         while ((symbolP  = *symbolPP) != NULL) {
412                 if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
413                         S_SET_SEGMENT(symbolP, SEG_TEXT);
414                 } /* if pusing data into text */
415                 
416                 S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
417                 
418                 /* OK, here is how we decide which symbols go out into the
419                    brave new symtab.  Symbols that do are:
420                    
421                    * symbols with no name (stabd's?)
422                    * symbols with debug info in their N_TYPE
423                    
424                    Symbols that don't are:
425                    * symbols that are registers
426                    * symbols with \1 as their 3rd character (numeric labels)
427                    * "local labels" as defined by S_LOCAL_NAME(name)
428                    if the -L switch was passed to gas.
429                    
430                    All other symbols are output.  We complain if a deleted
431                    symbol was marked external. */
432                 
433                 
434                 if (!S_IS_REGISTER(symbolP)
435                     && (!S_GET_NAME(symbolP)
436                         || S_IS_DEBUG(symbolP)
437 #ifdef TC_I960
438                         /* FIXME-SOON this ifdef seems highly dubious to me.  xoxorich. */
439                         || !S_IS_DEFINED(symbolP)
440                         || S_IS_EXTERNAL(symbolP)
441 #endif /* TC_I960 */
442                         || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))) {
443                         symbolP->sy_number = symbol_number++;
444                         
445                         /* The + 1 after strlen account for the \0 at the
446                            end of each string */
447                         if (!S_IS_STABD(symbolP)) {
448                                 /* Ordinary case. */
449                                 symbolP->sy_name_offset = string_byte_count;
450                                 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
451                         }
452                         else    /* .Stabd case. */
453                             symbolP->sy_name_offset = 0;
454                         symbolPP = &(symbol_next(symbolP));
455                 } else {
456                         if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
457                                 as_bad("Local symbol %s never defined.", decode_local_label_name(S_GET_NAME(symbolP)));
458                         } /* oops. */
459                         
460                         /* Unhook it from the chain */
461                         *symbolPP = symbol_next(symbolP);
462                 } /* if this symbol should be in the output */
463         } /* for each symbol */
464         
465         H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
466         
467         return;
468 } /* obj_crawl_symbol_chain() */
469
470 /*
471  * Find strings by crawling along symbol table chain.
472  */
473
474 void obj_emit_strings(where)
475 char **where;
476 {
477         symbolS *symbolP;
478         
479 #ifdef CROSS_COMPILE
480         /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
481         md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
482         *where += sizeof(string_byte_count);
483 #else /* CROSS_COMPILE */
484         append (where, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count));
485 #endif /* CROSS_COMPILE */
486         
487         for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
488                 if(S_GET_NAME(symbolP))
489                     append(&next_object_file_charP, S_GET_NAME(symbolP),
490                            (unsigned long)(strlen (S_GET_NAME(symbolP)) + 1));
491         } /* walk symbol chain */
492         
493         return;
494 } /* obj_emit_strings() */
495
496 void obj_pre_write_hook(headers)
497 object_headers *headers;
498 {
499         H_SET_DYNAMIC(headers, 0);
500         H_SET_VERSION(headers, 0);
501         H_SET_MACHTYPE(headers, AOUT_MACHTYPE);
502         tc_aout_pre_write_hook(headers);
503         return;
504 } /* obj_pre_write_hook() */
505
506 /*
507  * Local Variables:
508  * comment-column: 0
509  * fill-column: 131
510  * End:
511  */
512
513 /* end of obj-aout.c */