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