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