Initial import from FreeBSD RELENG_4:
[dragonfly.git] / gnu / usr.bin / as / config / obj-aout.c
1 /* a.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
24 #include <stab.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,    SEG_GOOF,       /* N_UNDF == 0 */
46         SEG_ABSOLUTE,   SEG_GOOF,       /* N_ABS == 2 */
47         SEG_TEXT,       SEG_GOOF,       /* N_TEXT == 4 */
48         SEG_DATA,       SEG_GOOF,       /* N_DATA == 6 */
49         SEG_BSS,        SEG_GOOF,       /* N_BSS == 8 */
50         SEG_GOOF,       SEG_GOOF,       /* N_INDR == 0xa */
51         SEG_GOOF,       SEG_GOOF,       /* 0xc */
52         SEG_GOOF,       SEG_GOOF,       /* 0xe */
53         SEG_GOOF,       SEG_GOOF,       /* 0x10 */
54         SEG_REGISTER,   SEG_GOOF,       /* 0x12 (dummy N_REGISTER) */
55         SEG_GOOF,       SEG_GOOF,       /* N_SETA == 0x14 */
56         SEG_GOOF,       SEG_GOOF,       /* N_SETT == 0x16 */
57         SEG_GOOF,       SEG_GOOF,       /* N_SETD == 0x18 */
58         SEG_GOOF,       SEG_GOOF,       /* N_SETB == 0x1a */
59         SEG_GOOF,       SEG_GOOF,       /* N_SETV == 0x1c */
60         SEG_GOOF,       SEG_GOOF,       /* N_WARNING == 0x1e */
61 };
62
63 #if __STDC__ == 1
64 static void obj_aout_stab(int what);
65 static void obj_aout_line(void);
66 static void obj_aout_desc(void);
67 #else /* not __STDC__ */
68 static void obj_aout_desc();
69 static void obj_aout_stab();
70 static void obj_aout_line();
71 #endif /* not __STDC__ */
72
73 const pseudo_typeS obj_pseudo_table[] = {
74 #ifndef IGNORE_DEBUG
75         /* stabs debug info */
76         { "line",       obj_aout_line,          0       }, /* source code line number */
77         { "ln",         obj_aout_line,          0       }, /* coff line number that we use anyway */
78         { "desc",       obj_aout_desc,          0       }, /* desc */
79         { "stabd",      obj_aout_stab,          'd'     }, /* stabs */
80         { "stabn",      obj_aout_stab,          'n'     }, /* stabs */
81         { "stabs",      obj_aout_stab,          's'     }, /* stabs */
82 #else /* IGNORE_DEBUG */
83         { "line",       obj_aout_line,          0       }, /* source code line number */
84         { "ln",         obj_aout_line,          0       }, /* coff line number that we use anyway */
85         { "desc",       obj_aout_desc,          0       }, /* desc */
86         { "stabd",      obj_aout_stab,          'd'     }, /* stabs */
87         { "stabn",      obj_aout_stab,          'n'     }, /* stabs */
88         { "stabs",      obj_aout_stab,          's'     }, /* stabs */
89 #endif /* IGNORE_DEBUG */
90
91         /* coff debug pseudos (ignored) */
92         { "def",        s_ignore, 0 },
93         { "dim",        s_ignore, 0 },
94         { "endef",      s_ignore, 0 },
95         { "ident",      s_ignore, 0 },
96         { "line",       s_ignore, 0 },
97         { "ln",         s_ignore, 0 },
98         { "scl",        s_ignore, 0 },
99         { "size",       s_size,   0 },
100         { "tag",        s_ignore, 0 },
101         { "type",       s_type, 0 },
102         { "val",        s_ignore, 0 },
103         { "version",    s_ignore, 0 },
104         { "weak",       s_weak, 0 },
105
106         /* stabs-in-coff (?) debug pseudos (ignored) */
107         { "optim",      s_ignore, 0 }, /* For sun386i cc (?) */
108
109         /* other stuff */
110         { "ABORT",      s_abort,                0 },
111
112         { NULL} /* end sentinel */
113 }; /* obj_pseudo_table */
114
115
116 /* Relocation. */
117
118 /*
119  *              emit_relocations()
120  *
121  * Crawl along a fixS chain. Emit the segment's relocations.
122  */
123 void obj_emit_relocations(where, fixP, segment_address_in_file)
124 char **where;
125 fixS *fixP; /* Fixup chain for this segment. */
126 relax_addressT segment_address_in_file;
127 {
128         for (;  fixP;  fixP = fixP->fx_next) {
129                 if (fixP->fx_addsy != NULL) {
130                         tc_aout_fix_to_chars(*where, fixP, segment_address_in_file);
131                         *where += md_reloc_size;
132                 } /* if there is an add symbol */
133         } /* for each fix */
134
135         return;
136 } /* obj_emit_relocations() */
137
138 /* Aout file generation & utilities */
139 void obj_header_append(where, headers)
140 char **where;
141 object_headers *headers;
142 {
143         tc_headers_hook(headers);
144
145 #if defined(NETBSD_AOUT)
146         /* `a_info' (magic, mid, flags) is in network byte-order */
147         (*where)[0] = ((char *)&headers->header.a_info)[0];
148         (*where)[1] = ((char *)&headers->header.a_info)[1];
149         (*where)[2] = ((char *)&headers->header.a_info)[2];
150         (*where)[3] = ((char *)&headers->header.a_info)[3];
151 #else
152         md_number_to_chars(*where, headers->header.a_info,
153                            sizeof(headers->header.a_info));
154 #endif
155         *where += sizeof(headers->header.a_info);
156
157 #ifdef TE_HPUX
158         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare1 */
159         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare2 */
160 #endif /* TE_HPUX */
161
162         md_number_to_chars(*where, headers->header.a_text, 4); *where += 4;
163         md_number_to_chars(*where, headers->header.a_data, 4); *where += 4;
164         md_number_to_chars(*where, headers->header.a_bss, 4); *where += 4;
165
166 #ifndef TE_HPUX
167         md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
168         md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
169 #endif /* not TE_HPUX */
170
171         md_number_to_chars(*where, headers->header.a_trsize, 4); *where += 4;
172         md_number_to_chars(*where, headers->header.a_drsize, 4); *where += 4;
173
174 #ifdef TE_SEQUENT
175         memset(*where, '\0', 3 * 2 * 4); *where += 3 * 2 * 4; /* global descriptor table? */
176         md_number_to_chars(*where, 0, 4); *where += 4; /* shdata - length of initialized shared data */
177         md_number_to_chars(*where, 0, 4); *where += 4; /* shbss - length of uninitialized shared data */
178         md_number_to_chars(*where, 0, 4); *where += 4; /* shdrsize - length of shared data relocation */
179
180         memset(*where, '\0', 11 * 4); *where += 11 * 4; /* boostrap for standalone */
181         memset(*where, '\0', 3 * 4); *where += 3 * 4; /* reserved */
182         md_number_to_chars(*where, 0, 4); *where += 4; /* version */
183 #endif /* TE_SEQUENT */
184
185 #ifdef TE_HPUX
186         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare3 - HP = pascal interface size */
187         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare4 - HP = symbol table size */
188         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare5 - HP = debug name table size */
189
190         md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
191
192         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare6 - HP = source line table size */
193         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare7 - HP = value table size */
194
195         md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
196
197         md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare8 */
198 #endif /* TE_HPUX */
199
200         return;
201 } /* obj_append_header() */
202
203 void obj_symbol_to_chars(where, symbolP)
204 char **where;
205 symbolS *symbolP;
206 {
207         md_number_to_chars((char *)&(S_GET_OFFSET(symbolP)), S_GET_OFFSET(symbolP), sizeof(S_GET_OFFSET(symbolP)));
208         md_number_to_chars((char *)&(S_GET_DESC(symbolP)), S_GET_DESC(symbolP), sizeof(S_GET_DESC(symbolP)));
209         md_number_to_chars((char *)&(S_GET_VALUE(symbolP)), S_GET_VALUE(symbolP), sizeof(S_GET_VALUE(symbolP)));
210
211         append(where, (char *)&symbolP->sy_symbol, sizeof(obj_symbol_type));
212 } /* obj_symbol_to_chars() */
213
214 void obj_emit_symbols(where, symbol_rootP)
215 char **where;
216 symbolS *symbol_rootP;
217 {
218         symbolS *       symbolP;
219
220         /*
221          * Emit all symbols left in the symbol chain.
222          */
223         for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
224                 /* Used to save the offset of the name. It is used to point
225                    to the string in memory but must be a file offset. */
226                 register char *temp;
227
228                 temp = S_GET_NAME(symbolP);
229                 S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
230
231                 /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
232                 if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP))
233                         S_SET_EXTERNAL(symbolP);
234
235                 /*
236                  * Put aux info in lower four bits of `n_other' field
237                  * Do this only now, because things like S_IS_DEFINED()
238                  * depend on S_GET_OTHER() for some unspecified reason.
239                  */
240                 S_SET_OTHER(symbolP,
241                         (symbolP->sy_bind << 4) | (symbolP->sy_aux & 0xf));
242
243                 if (S_GET_TYPE(symbolP) == N_SIZE) {
244                         expressionS     *exp = (expressionS*)symbolP->sy_sizexp;
245                         long            size = 0;
246
247                         if (exp == NULL) {
248                                 as_bad("Internal error: no size expression");
249                                 return;
250                         }
251
252                         switch (exp->X_seg) {
253                         case SEG_ABSOLUTE:
254                                 size = exp->X_add_number;
255                                 break;
256                         case SEG_DIFFERENCE:
257                                 size = S_GET_VALUE(exp->X_add_symbol) -
258                                         S_GET_VALUE(exp->X_subtract_symbol) +
259                                         exp->X_add_number;
260                                 break;
261                         default:
262                                 as_bad("Unsupported .size expression");
263                                 break;
264                         }
265                         S_SET_VALUE(symbolP, size);
266                 }
267
268                 obj_symbol_to_chars(where, symbolP);
269                 S_SET_NAME(symbolP,temp);
270         }
271 } /* emit_symbols() */
272
273 #if comment
274 /* uneeded if symbol is born zeroed. */
275 void obj_symbol_new_hook(symbolP)
276 symbolS *symbolP;
277 {
278         S_SET_OTHER(symbolP, 0);
279         S_SET_DESC(symbolP, 0);
280         return;
281 } /* obj_symbol_new_hook() */
282 #endif /* comment */
283
284 static void obj_aout_line() {
285         /* Assume delimiter is part of expression. */
286         /* BSD4.2 as fails with delightful bug, so we */
287         /* are not being incompatible here. */
288         new_logical_line((char *)NULL, (int)(get_absolute_expression()));
289         demand_empty_rest_of_line();
290 } /* obj_aout_line() */
291
292 /*
293  *                      stab()
294  *
295  * Handle .stabX directives, which used to be open-coded.
296  * So much creeping featurism overloaded the semantics that we decided
297  * to put all .stabX thinking in one place. Here.
298  *
299  * We try to make any .stabX directive legal. Other people's AS will often
300  * do assembly-time consistency checks: eg assigning meaning to n_type bits
301  * and "protecting" you from setting them to certain values. (They also zero
302  * certain bits before emitting symbols. Tut tut.)
303  *
304  * If an expression is not absolute we either gripe or use the relocation
305  * information. Other people's assemblers silently forget information they
306  * don't need and invent information they need that you didn't supply.
307  *
308  * .stabX directives always make a symbol table entry. It may be junk if
309  * the rest of your .stabX directive is malformed.
310  */
311 static void obj_aout_stab(what)
312 int what;
313 {
314 #ifndef NO_LISTING
315         extern int listing;
316 #endif /* NO_LISTING */
317
318         register symbolS *symbolP = 0;
319         register char *string;
320         int saved_type = 0;
321         int length;
322         int goof; /* TRUE if we have aborted. */
323         long longint;
324
325         /*
326          * Enter with input_line_pointer pointing past .stabX and any following
327          * whitespace.
328          */
329         goof = 0; /* JF who forgot this?? */
330         if (what == 's') {
331                 string = demand_copy_C_string(& length);
332                 SKIP_WHITESPACE();
333                 if (* input_line_pointer == ',')
334                     input_line_pointer ++;
335                 else {
336                         as_bad("I need a comma after symbol's name");
337                         goof = 1;
338                 }
339         } else
340             string = "";
341
342         /*
343          * Input_line_pointer->after ','.  String->symbol name.
344          */
345         if (! goof) {
346                 symbolP = symbol_new(string,
347                                      SEG_UNKNOWN,
348                                      0,
349                                      (struct frag *)0);
350                 switch (what) {
351                 case 'd':
352                         S_SET_NAME(symbolP, NULL); /* .stabd feature. */
353                         S_SET_VALUE(symbolP, obstack_next_free(&frags) - frag_now->fr_literal);
354                         symbolP->sy_frag = frag_now;
355                         break;
356
357                 case 'n':
358                         symbolP->sy_frag = &zero_address_frag;
359                         break;
360
361                 case 's':
362                         symbolP->sy_frag = & zero_address_frag;
363                         break;
364
365                 default:
366                         BAD_CASE(what);
367                         break;
368                 }
369
370                 if (get_absolute_expression_and_terminator(&longint) == ',')
371                     symbolP->sy_symbol.n_type = saved_type = longint;
372                 else {
373                         as_bad("I want a comma after the n_type expression");
374                         goof = 1;
375                         input_line_pointer --; /* Backup over a non-',' char. */
376                 }
377         }
378
379         if (!goof) {
380                 if (get_absolute_expression_and_terminator(&longint) == ',')
381                     S_SET_OTHER(symbolP, longint);
382                 else {
383                         as_bad("I want a comma after the n_other expression");
384                         goof = 1;
385                         input_line_pointer--; /* Backup over a non-',' char. */
386                 }
387         }
388
389         if (!goof) {
390                 S_SET_DESC(symbolP, get_absolute_expression());
391                 if (what == 's' || what == 'n') {
392                         if (*input_line_pointer != ',') {
393                                 as_bad("I want a comma after the n_desc expression");
394                                 goof = 1;
395                         } else {
396                                 input_line_pointer++;
397                         }
398                 }
399         }
400
401         if ((!goof) && (what == 's' || what == 'n')) {
402                 pseudo_set(symbolP);
403                 symbolP->sy_symbol.n_type = saved_type;
404         }
405 #ifndef NO_LISTING
406         if (listing && !goof)
407             {
408                     if (symbolP->sy_symbol.n_type == N_SLINE)
409                         {
410
411                                 listing_source_line(symbolP->sy_symbol.n_desc);
412                         }
413                     else if (symbolP->sy_symbol.n_type == N_SO
414                              || symbolP->sy_symbol.n_type == N_SOL)
415                         {
416                                 listing_source_file(string);
417                         }
418             }
419 #endif
420
421         if (goof)
422             ignore_rest_of_line();
423         else
424             demand_empty_rest_of_line ();
425 } /* obj_aout_stab() */
426
427 static void obj_aout_desc() {
428         register char *name;
429         register char c;
430         register char *p;
431         register symbolS *symbolP;
432         register int temp;
433
434         /*
435          * Frob invented at RMS' request. Set the n_desc of a symbol.
436          */
437         name = input_line_pointer;
438         c = get_symbol_end();
439         p = input_line_pointer;
440         * p = c;
441         SKIP_WHITESPACE();
442         if (*input_line_pointer != ',') {
443                 *p = 0;
444                 as_bad("Expected comma after name \"%s\"", name);
445                 *p = c;
446                 ignore_rest_of_line();
447         } else {
448                 input_line_pointer ++;
449                 temp = get_absolute_expression();
450                 *p = 0;
451                 symbolP = symbol_find_or_make(name);
452                 *p = c;
453                 S_SET_DESC(symbolP,temp);
454         }
455         demand_empty_rest_of_line();
456 } /* obj_aout_desc() */
457
458 void obj_read_begin_hook() {
459         return;
460 } /* obj_read_begin_hook() */
461
462 void obj_crawl_symbol_chain(headers)
463 object_headers *headers;
464 {
465         symbolS *symbolP;
466         symbolS **symbolPP;
467         int symbol_number = 0;
468
469         /* JF deal with forward references first... */
470         for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
471                 if (symbolP->sy_forward && symbolP->sy_forward != symbolP) {
472                         switch (S_GET_TYPE(symbolP)) {
473
474                         case N_SETA:
475                         case N_SETT:
476                         case N_SETD:
477                         case N_SETB:
478                                 /*
479                                  * Don't change the segments of SET symbols,
480                                  * because that would turn them into regular
481                                  * symbols.
482                                  */
483                                 break;
484
485                         default:
486                                 S_SET_SEGMENT(symbolP,
487                                     S_GET_SEGMENT(symbolP->sy_forward));
488                                 break;
489                         }
490                         S_SET_VALUE(symbolP, S_GET_VALUE(symbolP)
491                                     + S_GET_VALUE(symbolP->sy_forward)
492                                     + symbolP->sy_forward->sy_frag->fr_address);
493
494                         symbolP->sy_aux |= symbolP->sy_forward->sy_aux;
495                         symbolP->sy_sizexp = symbolP->sy_forward->sy_sizexp;
496                         if (S_IS_EXTERNAL(symbolP->sy_forward))
497                                 S_SET_EXTERNAL(symbolP);
498                 } /* if it has a forward reference */
499                 symbolP->sy_forward=0;
500         } /* walk the symbol chain */
501
502         tc_crawl_symbol_chain(headers);
503
504         symbolPP = &symbol_rootP;       /*->last symbol chain link. */
505         while ((symbolP  = *symbolPP) != NULL) {
506                 if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
507                         S_SET_SEGMENT(symbolP, SEG_TEXT);
508                 } /* if pushing data into text */
509
510                 S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
511
512                 /* OK, here is how we decide which symbols go out into the
513                    brave new symtab.  Symbols that do are:
514
515                    * symbols with no name (stabd's?)
516                    * symbols with debug info in their N_TYPE
517                    * symbols marked "forceout" (to force out local `L'
518                                                 symbols in PIC code)
519
520                    Symbols that don't are:
521                    * symbols that are registers
522                    * symbols with \1 as their 3rd character (numeric labels)
523                    * "local labels" as defined by S_LOCAL_NAME(name)
524                    if the -L switch was passed to gas.
525
526                    All other symbols are output.  We complain if a deleted
527                    symbol was marked external. */
528
529
530                 if (!S_IS_REGISTER(symbolP)
531                     && (!S_GET_NAME(symbolP)
532                         || S_IS_DEBUG(symbolP)
533 #ifdef TC_I960
534                         /* FIXME-SOON this ifdef seems highly dubious to me.  xoxorich. */
535                         || !S_IS_DEFINED(symbolP)
536                         || S_IS_EXTERNAL(symbolP)
537 #endif /* TC_I960 */
538                         || (S_GET_NAME(symbolP)[0] != '\001' &&
539                                 (flagseen['L'] || ! S_LOCAL_NAME(symbolP))
540 #ifdef PIC
541                                 || (picmode && symbolP->sy_forceout)
542 #endif
543                            )
544                         )
545 #ifdef PIC
546                      && (!picmode ||
547                                 symbolP != GOT_symbol || got_referenced != 0
548                         )
549 #endif
550                     ) {
551                         symbolP->sy_number = symbol_number++;
552
553                         /* The + 1 after strlen account for the \0 at the
554                            end of each string */
555                         if (!S_IS_STABD(symbolP)) {
556                                 /* Ordinary case. */
557                                 symbolP->sy_name_offset = string_byte_count;
558                                 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
559                         }
560                         else    /* .Stabd case. */
561                             symbolP->sy_name_offset = 0;
562
563                         /*
564                          * If symbol has a known size, output an extra symbol
565                          * of type N_SIZE and with the same name.
566                          * We cannot evaluate the size expression just yet, as
567                          * some its terms may not have had their final values
568                          * set. We defer this until `obj_emit_symbols()'
569                          */
570                         if (picmode &&
571                                 S_GET_TYPE(symbolP) != N_SIZE &&
572 #ifndef GRACE_PERIOD_EXPIRED
573                                 /*Can be enabled when no more old ld's around*/
574                                 (symbolP->sy_aux == AUX_OBJECT) &&
575 #endif
576                                         symbolP->sy_sizexp) {
577
578                                 symbolS         *addme;
579
580                                 /* Put a new symbol on the chain */
581 #ifdef NSIZE_PREFIX /*XXX*/
582                                 char    buf[BUFSIZ];
583
584                                 buf[0] = NSIZE_PREFIX;
585                                 strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2);
586                                 addme = symbol_make(buf);
587 #else
588                                 addme = symbol_make(S_GET_NAME(symbolP));
589 #endif
590                                 /* Set type and transfer size expression */
591                                 addme->sy_symbol.n_type = N_SIZE;
592                                 addme->sy_sizexp = symbolP->sy_sizexp;
593                                 symbolP->sy_sizexp = NULL;
594
595                                 /* Set external if symbolP is */
596                                 if (S_IS_EXTERN(symbolP))
597                                         S_SET_EXTERNAL(addme);
598
599                         }
600                         symbolPP = &(symbol_next(symbolP));
601                 } else {
602                         if ((S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP))
603 #ifdef PIC
604                              && (!picmode ||
605                                 symbolP != GOT_symbol || got_referenced != 0
606                                 )
607 #endif
608                         ) {
609                                 as_bad("Local symbol %s never defined.", decode_local_label_name(S_GET_NAME(symbolP)));
610                         } /* oops. */
611
612                         /* Unhook it from the chain */
613                         *symbolPP = symbol_next(symbolP);
614                 } /* if this symbol should be in the output */
615         } /* for each symbol */
616
617         H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
618
619         return;
620 } /* obj_crawl_symbol_chain() */
621
622 /*
623  * Find strings by crawling along symbol table chain.
624  */
625
626 void obj_emit_strings(where)
627 char **where;
628 {
629         symbolS *symbolP;
630
631 #ifdef CROSS_COMPILE
632         /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
633         md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
634         *where += sizeof(string_byte_count);
635 #else /* CROSS_COMPILE */
636         append (where, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count));
637 #endif /* CROSS_COMPILE */
638
639         for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
640                 if (S_GET_NAME(symbolP))
641                     append(&next_object_file_charP, S_GET_NAME(symbolP),
642                            (unsigned long)(strlen (S_GET_NAME(symbolP)) + 1));
643         } /* walk symbol chain */
644
645         return;
646 } /* obj_emit_strings() */
647
648 void obj_pre_write_hook(headers)
649 object_headers *headers;
650 {
651         H_SET_INFO(headers,
652                    DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE,
653                    AOUT_MACHTYPE,
654                    AOUT_FLAGS,
655                    AOUT_VERSION);
656
657         H_SET_ENTRY_POINT(headers, 0);
658
659         tc_aout_pre_write_hook(headers);
660         return;
661 } /* obj_pre_write_hook() */
662
663 /*
664  * Local Variables:
665  * comment-column: 0
666  * fill-column: 131
667  * End:
668  */
669
670 /* end of obj-aout.c */