5f4f1812a39c040d4a5d6318d867a025e6e38470
[external/binutils.git] / gas / config / obj-elf.c
1 /* ELF object file format
2    Copyright (C) 1992, 1993 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 "subsegs.h"
22 #include "aout/stab_gnu.h"
23 #include "obstack.h"
24
25 static void obj_elf_stab PARAMS ((int what));
26 static void obj_elf_xstab PARAMS ((int what));
27 static void obj_elf_line PARAMS ((void));
28 void obj_elf_desc PARAMS ((void));
29 void obj_elf_version PARAMS ((void));
30 static void obj_elf_section PARAMS ((int));
31 static void obj_elf_size PARAMS ((void));
32 static void obj_elf_type PARAMS ((void));
33 static void obj_elf_ident PARAMS ((void));
34 static void obj_elf_previous PARAMS ((void));
35
36 const pseudo_typeS obj_pseudo_table[] =
37 {
38   {"ident", obj_elf_ident, 0},
39   {"previous", obj_elf_previous, 0},
40   {"section", obj_elf_section, 0},
41   {"size", obj_elf_size, 0},
42   {"type", obj_elf_type, 0},
43   {"version", obj_elf_version, 0},
44
45 /* These are used for stabs-in-elf configurations.  */
46   {"desc", obj_elf_desc, 0},
47   {"line", obj_elf_line, 0},
48   {"stabd", obj_elf_stab, 'd'},
49   {"stabn", obj_elf_stab, 'n'},
50   {"stabs", obj_elf_stab, 's'},
51 /* This is used on Solaris 2.x on SPARC, but not supported yet.  */
52   {"xstabs", obj_elf_xstab, 's'},
53
54   /* These are used for dwarf. */
55   {"2byte", cons, 2},
56   {"4byte", cons, 4},
57
58   {NULL}                        /* end sentinel */
59 };
60
61 #include "aout/aout64.h"
62
63 void
64 elf_file_symbol (s)
65      char *s;
66 {
67   symbolS *sym;
68
69   sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
70   sym->sy_frag = &zero_address_frag;
71   sym->bsym->flags |= BSF_FILE;
72
73   if (symbol_rootP != sym)
74     {
75       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
76       symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
77 #ifdef DEBUG
78       verify_symbol_chain (symbol_rootP, symbol_lastP);
79 #endif
80     }
81 }
82
83 static segT previous_section;
84 static int previous_subsection;
85
86 static void
87 obj_elf_section (xxx)
88      int xxx;
89 {
90   char *string;
91   asection *sec;
92
93   /* Initialize this with inclusive-or of all flags that can be cleared
94      by attributes, but not set by them.  Also include flags that won't
95      get set properly in the assembler, but which the user/compiler
96      shouldn't be expected to set.  */
97   flagword flags = SEC_READONLY | SEC_ALLOC | SEC_RELOC;
98   /* Initialize this with the default flags to be used if none are
99      specified.  */
100   flagword default_flags = 0;
101
102   SKIP_WHITESPACE ();
103   if (*input_line_pointer == '"')
104     string = demand_copy_C_string (&xxx);
105   else
106     {
107       char *p = input_line_pointer;
108       char c;
109       while (0 == strchr ("\n\t,; ", *p))
110         p++;
111       c = *p;
112       *p = 0;
113       string = xmalloc (p - input_line_pointer + 1);
114       strcpy (string, input_line_pointer);
115       *p = c;
116       input_line_pointer = p;
117     }
118   if (!strcmp (string, ".rodata"))
119       default_flags = SEC_ALLOC | SEC_READONLY | SEC_RELOC;
120   SKIP_WHITESPACE ();
121   if (*input_line_pointer != ',')
122     flags = default_flags;
123   while (*input_line_pointer == ',')
124     {
125       flagword bit;
126       int len, inv;
127       char *p, oldp;
128
129       input_line_pointer++;
130       if (*input_line_pointer != '#' && *input_line_pointer != '@')
131         {
132           as_bad ("unrecognized syntax in .section command");
133           ignore_rest_of_line ();
134           break;
135         }
136       input_line_pointer++;
137
138 #define CHECK(X,BIT,NEG)        \
139       if (!strncmp(X,input_line_pointer,len = sizeof(X) - 1)) { \
140         bit = BIT; inv = NEG; goto match; }
141
142       CHECK ("write", SEC_READONLY, 1);
143       CHECK ("alloc", SEC_ALLOC, 0);
144       CHECK ("execinstr", SEC_CODE, 1);
145 #undef CHECK
146
147       p = input_line_pointer;
148       while (!is_end_of_line[*p] && *p != 0 && *p != ',')
149         p++;
150       *p = 0;
151       oldp = *p;
152       as_bad ("unrecognized section attribute `%s' ignored",
153               input_line_pointer);
154       *p = oldp;
155       continue;
156
157     match:
158       if (inv)
159         flags &= ~bit;
160       else
161         flags |= bit;
162       input_line_pointer += len;
163     }
164   demand_empty_rest_of_line ();
165
166   /* If the C string wasn't valid, `string' could be null.  */
167   if (!string)
168     return;
169
170   sec = bfd_get_section_by_name (stdoutput, string);
171   if (sec == 0)
172     {
173       sec = subseg_new (string, 0);
174       bfd_set_section_flags (stdoutput, sec, flags);
175       sec->output_section = sec;
176     }
177   previous_section = now_seg;
178   previous_subsection = now_subseg;
179   subseg_set (sec, 0);
180 }
181
182 static void
183 obj_elf_previous ()
184 {
185   if (previous_section == 0)
186     {
187       as_bad (".previous without corresponding .section; ignored");
188       return;
189     }
190   subseg_set (previous_section, previous_subsection);
191   previous_section = 0;
192 }
193
194 int
195 obj_elf_write_symbol_p (sym)
196      symbolS *sym;
197 {
198   /* If this is a local symbol, are there any relocations for which
199      need this symbol? */
200
201   /* To find this out, we examine all relocations in all bfd sections
202      that have relocations.  If there is one that references this
203      symbol, we need to keep this symbol.  In this case, we return a
204      true status.  In all other cases, we return a false status. */
205
206   if (S_IS_LOCAL (sym))
207     {
208       asymbol *bsym = sym->bsym;
209       bfd *abfd = bsym->the_bfd;
210       asection *bsec;
211
212       for (bsec = abfd->sections; bsec; bsec = bsec->next)
213         {
214           struct reloc_cache_entry **rlocs = bsec->orelocation;
215           int rcnt = bsec->reloc_count;
216
217           if (rlocs)
218             {
219               int i;
220
221               for (i = 0; i < rcnt; i++)
222                 if (rlocs[i]->sym_ptr_ptr
223                     && rlocs[i]->sym_ptr_ptr[0] == bsym)
224                   return 1;
225             }
226           else
227             {
228               /* No relocations for this section.  Check the seg_info
229                  structure to see if there are any fixups for this
230                  section. */
231               segment_info_type *seginfo = seg_info (bsec);
232               fixS *fixp;
233
234               for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
235                 if ((fixp->fx_addsy && fixp->fx_addsy->bsym == bsym)
236                     || (fixp->fx_subsy && fixp->fx_subsy->bsym == bsym))
237                   return 1;
238             }
239         }
240     }
241   return 0;
242 }
243
244 int
245 obj_elf_write_symbol (sym)
246      symbolS *sym;
247 {
248   return /* obj_elf_write_symbol_p (sym) || */ !S_IS_LOCAL (sym);
249 }
250
251 int
252 obj_elf_frob_symbol (sym, punt)
253      symbolS *sym;
254      int *punt;
255 {
256   return obj_elf_write_symbol_p (sym);
257 }
258
259 static void
260 obj_elf_line ()
261 {
262   /* Assume delimiter is part of expression.  BSD4.2 as fails with
263      delightful bug, so we are not being incompatible here. */
264   new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
265   demand_empty_rest_of_line ();
266 }
267
268 /*
269  *                      stab()
270  *
271  * Handle .stabX directives, which used to be open-coded.
272  * So much creeping featurism overloaded the semantics that we decided
273  * to put all .stabX thinking in one place. Here.
274  *
275  * We try to make any .stabX directive legal. Other people's AS will often
276  * do assembly-time consistency checks: eg assigning meaning to n_type bits
277  * and "protecting" you from setting them to certain values. (They also zero
278  * certain bits before emitting symbols. Tut tut.)
279  *
280  * If an expression is not absolute we either gripe or use the relocation
281  * information. Other people's assemblers silently forget information they
282  * don't need and invent information they need that you didn't supply.
283  *
284  * .stabX directives always make a symbol table entry. It may be junk if
285  * the rest of your .stabX directive is malformed.
286  */
287
288 /*
289  *                      elf_stab_symbol_string()
290  *
291  * Build a string dictionary entry for a .stabX symbol.
292  * The symbol is added to the .stabstr section.
293  *
294  */
295
296 static unsigned int
297 elf_stab_symbol_string (string, secname)
298      char *string, *secname;
299 {
300   asection *save_seg;
301   asection *seg;
302   subsegT save_subseg;
303   unsigned int length;
304   unsigned int old_gdb_string_index;
305   char *clengthP;
306   int i;
307   char c;
308   /* @@FIXME -- there should be no static data here!
309      This also has the effect of making all stab string tables large enough
310      to contain all the contents written to any of them.  This only matters
311      with the Solaris native compiler for the moment, but it should be fixed
312      anyways.  */
313   static unsigned int gdb_string_index = 0;
314
315   old_gdb_string_index = 0;
316   length = strlen (string);
317   clengthP = (char *) &length;
318   if (length > 0)
319     {                           /* Ordinary case. */
320       save_seg = now_seg;
321       save_subseg = now_subseg;
322
323       /* Create the stab sections, if they are not already created. */
324       {
325         char *newsecname = xmalloc (strlen (secname) + 4);
326         strcpy (newsecname, secname);
327         strcat (newsecname, "str");
328         seg = bfd_get_section_by_name (stdoutput, newsecname);
329         if (seg == 0)
330           {
331             seg = bfd_make_section_old_way (stdoutput, newsecname);
332             bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_ALLOC);
333           }
334 /*      free (newsecname);*/
335       }
336       subseg_new ((char *) seg->name, save_subseg);
337       old_gdb_string_index = gdb_string_index;
338       i = 0;
339       while ((c = *string++))
340         {
341           i++;
342           gdb_string_index++;
343           FRAG_APPEND_1_CHAR (c);
344         }
345       {
346         FRAG_APPEND_1_CHAR ((char) 0);
347         i++;
348         gdb_string_index++;
349       }
350       while (i % 4 != 0)
351         {
352           FRAG_APPEND_1_CHAR ((char) 0);
353           i++;
354           gdb_string_index++;
355         }
356       subseg_new ((char *) save_seg->name, save_subseg);
357     }
358
359   return old_gdb_string_index;
360 }
361
362 static void
363 DEFUN (elf_stab_symbol, (symbolP, stab_type),
364        symbolS *symbolP AND
365        int stab_type)
366 {
367   char *toP;
368
369   toP = frag_more (8);
370   /* the string index portion of the stab */
371   md_number_to_chars (toP, (valueT) symbolP->sy_name_offset, 4);
372   md_number_to_chars (toP + 4, (valueT) S_GET_TYPE (symbolP), 1);
373   md_number_to_chars (toP + 5, (valueT) S_GET_OTHER (symbolP), 1);
374   md_number_to_chars (toP + 6, (valueT) S_GET_DESC (symbolP), 2);
375   /* The n_value field doesn't get written here, it gets done below.  It
376      may be an expression needing relocating.  */
377 }
378
379 static void 
380 obj_elf_stab_generic (what, secname)
381      int what;
382      char *secname;
383 {
384   extern int listing;
385
386   symbolS *symbolP = 0;
387   char *string;
388   int saved_type = 0;
389   int length;
390   int goof = 0;
391   long longint;
392   asection *saved_seg = now_seg;
393   asection *seg;
394   subsegT subseg = now_subseg;
395
396 #if 1
397   /* This function doesn't work yet.
398
399      Actually, this function is okay, but some finalizations are needed
400      before writing the object file; that's not done yet, and the Solaris
401      linker chokes without it.
402
403      In any case, this should effectively disable it for now.  */
404   if (what == 's')
405     demand_copy_C_string (&length);
406   s_ignore (69);
407   return;
408 #endif
409
410   seg = bfd_get_section_by_name (stdoutput, secname);
411   if (seg == 0)
412     {
413       seg = subseg_new (secname, 0);
414       bfd_set_section_flags (stdoutput, seg,
415                              SEC_READONLY | SEC_ALLOC | SEC_RELOC);
416       subseg_set (saved_seg, subseg);
417     }
418
419   /*
420    * Enter with input_line_pointer pointing past .stabX and any following
421    * whitespace.
422    */
423   if (what == 's')
424     {
425       string = demand_copy_C_string (&length);
426       SKIP_WHITESPACE ();
427       if (*input_line_pointer == ',')
428         input_line_pointer++;
429       else
430         {
431           as_bad ("I need a comma after symbol's name");
432           goof = 1;
433         }
434     }
435   else
436     string = "";
437
438   /*
439    * Input_line_pointer->after ','.  String->symbol name.
440    */
441   if (!goof)
442     {
443       symbolP = symbol_new (string, &bfd_und_section, (valueT) 0, (struct frag *) 0);
444
445       /* enter the string in the .stab string table (section .stabstr) */
446       symbolP->sy_name_offset = elf_stab_symbol_string (string, secname);
447
448       switch (what)
449         {
450         case 'd':
451           S_SET_NAME (symbolP, NULL);   /* .stabd feature. */
452           S_SET_VALUE (symbolP,
453                        (valueT) ((char*) obstack_next_free (&frags) - frag_now->fr_literal));
454           S_SET_SEGMENT (symbolP, now_seg);
455           symbolP->sy_frag = frag_now;
456           break;
457
458         case 'n':
459           symbolP->sy_frag = &zero_address_frag;
460           break;
461
462         case 's':
463           symbolP->sy_frag = &zero_address_frag;
464           break;
465
466         default:
467           BAD_CASE (what);
468           break;
469         }
470
471       if (get_absolute_expression_and_terminator (&longint) == ',')
472         {
473           saved_type = longint;
474           S_SET_TYPE (symbolP, saved_type);
475         }
476       else
477         {
478           as_bad ("I want a comma after the n_type expression");
479           goof = 1;
480           input_line_pointer--; /* Backup over a non-',' char. */
481         }
482     }
483
484   if (!goof)
485     {
486       if (get_absolute_expression_and_terminator (&longint) == ',')
487         S_SET_OTHER (symbolP, longint);
488       else
489         {
490           as_bad ("I want a comma after the n_other expression");
491           goof = 1;
492           input_line_pointer--; /* Backup over a non-',' char. */
493         }
494     }
495
496   if (!goof)
497     {
498       S_SET_DESC (symbolP, get_absolute_expression ());
499       if (what == 's' || what == 'n')
500         {
501           if (*input_line_pointer != ',')
502             {
503               as_bad ("I want a comma after the n_desc expression");
504               goof = 1;
505             }
506           else
507             {
508               input_line_pointer++;
509             }
510         }
511     }
512
513   if (!goof)
514     {
515       subseg_new ((char *) seg->name, subseg);
516
517       /* Emit the stab symbol. */
518       elf_stab_symbol (symbolP, what);
519
520       if (what == 's' || what == 'n')
521         {
522           cons (4);
523           input_line_pointer--;
524         }
525       else
526         {
527           char *p = frag_more (4);
528           md_number_to_chars (p, 0, 0);
529         }
530       subseg_new ((char *) saved_seg->name, subseg);
531
532       if ((what == 's' || what == 'n')
533           && symbolP->sy_value.X_seg == absolute_section)
534         {
535           /* symbol is not needed in the regular symbol table */
536           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
537         }
538
539     }
540
541 #ifndef NO_LISTING
542   if (listing && !goof)
543     switch (S_GET_TYPE (symbolP))
544       {
545       case N_SLINE:
546         listing_source_line (S_GET_DESC (symbolP));
547         break;
548       case N_SO:
549       case N_SOL:
550         listing_source_file (string);
551         break;
552       }
553 #endif
554
555   if (goof)
556     ignore_rest_of_line ();
557   else
558     demand_empty_rest_of_line ();
559 }
560
561 static void
562 obj_elf_stab (what)
563      int what;
564 {
565   obj_elf_stab_generic (what, ".stab");
566 }
567
568 static void
569 obj_elf_xstab (what)
570      int what;
571 {
572   int length;
573   char *secname;
574
575   secname = demand_copy_C_string (&length);
576   SKIP_WHITESPACE ();
577   if (*input_line_pointer == ',')
578     input_line_pointer++;
579   else
580     {
581       as_bad ("comma missing in .xstabs");
582       ignore_rest_of_line ();
583       return;
584     }
585   obj_elf_stab_generic (what, secname);
586 }
587
588 void 
589 obj_elf_desc ()
590 {
591   char *name;
592   char c;
593   char *p;
594   symbolS *symbolP;
595   int temp;
596
597   /* Frob invented at RMS' request. Set the n_desc of a symbol.  */
598   name = input_line_pointer;
599   c = get_symbol_end ();
600   p = input_line_pointer;
601   *p = c;
602   SKIP_WHITESPACE ();
603   if (*input_line_pointer != ',')
604     {
605       *p = 0;
606       as_bad ("Expected comma after name \"%s\"", name);
607       *p = c;
608       ignore_rest_of_line ();
609     }
610   else
611     {
612       input_line_pointer++;
613       temp = get_absolute_expression ();
614       *p = 0;
615       symbolP = symbol_find_or_make (name);
616       *p = c;
617       S_SET_DESC (symbolP, temp);
618     }
619   demand_empty_rest_of_line ();
620 }                               /* obj_elf_desc() */
621
622 void 
623 obj_read_begin_hook ()
624 {
625 }
626
627 void 
628 obj_symbol_new_hook (symbolP)
629      symbolS *symbolP;
630 {
631 #if 0 /* BFD already takes care of this */
632   elf32_symbol_type *esym = (elf32_symbol_type *) symbolP;
633
634   /* There is an Elf_Internal_Sym and an Elf_External_Sym.  For now,
635      just zero them out.  */
636
637   bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym));
638   bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym));
639   bzero ((char *) &esym->tc_data, sizeof (esym->tc_data));
640 #endif
641 }
642
643 void 
644 obj_elf_version ()
645 {
646   char *name;
647   unsigned int c;
648   char ch;
649   char *p;
650   asection *seg = now_seg;
651   subsegT subseg = now_subseg;
652   Elf_Internal_Note i_note;
653   Elf_External_Note e_note;
654   asection *note_secp = (asection *) NULL;
655   int i, len;
656
657   SKIP_WHITESPACE ();
658   if (*input_line_pointer == '\"')
659     {
660       ++input_line_pointer;     /* -> 1st char of string. */
661       name = input_line_pointer;
662
663       while (is_a_char (c = next_char_of_string ()))
664         ;
665       c = *input_line_pointer;
666       *input_line_pointer = '\0';
667       *(input_line_pointer - 1) = '\0';
668       *input_line_pointer = c;
669
670       /* create the .note section if this is the first version string */
671
672       note_secp = bfd_get_section_by_name (stdoutput, ".note");
673       if (note_secp == (asection *) NULL)
674         {
675           note_secp = bfd_make_section_old_way (stdoutput, ".note");
676           bfd_set_section_flags (stdoutput,
677                                  note_secp,
678                                  SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS);
679         }
680
681       /* process the version string */
682
683       subseg_new ((char *) note_secp->name, 0);
684       len = strlen (name);
685
686       i_note.namesz = ((len + 1) + 3) & ~3;     /* round this to word boundary  */
687       i_note.descsz = 0;        /* no description       */
688       i_note.type = NT_VERSION;
689       p = frag_more (sizeof (e_note.namesz));
690       md_number_to_chars (p, (valueT) i_note.namesz, 4);
691       p = frag_more (sizeof (e_note.descsz));
692       md_number_to_chars (p, (valueT) i_note.descsz, 4);
693       p = frag_more (sizeof (e_note.type));
694       md_number_to_chars (p, (valueT) i_note.type, 4);
695
696       for (i = 0; i < len; i++)
697         {
698           ch = *(name + i);
699           {
700             FRAG_APPEND_1_CHAR (ch);
701           }
702         }
703       frag_align (2, 0);
704
705       subseg_new ((char *) seg->name, subseg);
706     }
707   else
708     {
709       as_bad ("Expected \"-ed string");
710     }
711   demand_empty_rest_of_line ();
712 }
713
714 static void
715 obj_elf_size ()
716 {
717   char *name = input_line_pointer;
718   char c = get_symbol_end ();
719   char *p;
720   expressionS exp;
721   segT sec;
722   symbolS *sym;
723
724   p = input_line_pointer;
725   *p = c;
726   SKIP_WHITESPACE ();
727   if (*input_line_pointer != ',')
728     {
729       *p = 0;
730       as_bad ("expected comma after name `%s' in .size directive", name);
731       *p = c;
732       ignore_rest_of_line ();
733       return;
734     }
735   input_line_pointer++;
736   sec = expression (&exp);
737   if (sec == absent_section)
738     {
739       as_bad ("missing expression in .size directive");
740       exp.X_seg = absolute_section;
741       exp.X_add_number = 0;
742     }
743   *p = 0;
744   sym = symbol_find_or_make (name);
745   *p = c;
746   if (sec == absolute_section)
747     S_SET_SIZE (sym, exp.X_add_number);
748   else
749     {
750 #if 0
751       static int warned;
752       if (!warned)
753         {
754           as_tsktsk (".size expressions not yet supported, ignored");
755           warned++;
756         }
757 #endif
758     }
759   demand_empty_rest_of_line ();
760 }
761
762 static void
763 obj_elf_type ()
764 {
765   char *name = input_line_pointer;
766   char c = get_symbol_end ();
767   char *p;
768   int type = 0;
769   symbolS *sym;
770
771   p = input_line_pointer;
772   *p = c;
773   SKIP_WHITESPACE ();
774   if (*input_line_pointer != ',')
775     {
776       as_bad ("expected comma after name in .type directive");
777     egress:
778       ignore_rest_of_line ();
779       return;
780     }
781   input_line_pointer++;
782   SKIP_WHITESPACE ();
783   if (*input_line_pointer != '#')
784     {
785       as_bad ("expected `#' after comma in .type directive");
786       goto egress;
787     }
788   input_line_pointer++;
789   if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1))
790     {
791       type = BSF_FUNCTION;
792       input_line_pointer += sizeof ("function") - 1;
793     }
794   else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1))
795     {
796       input_line_pointer += sizeof ("object") - 1;
797     }
798   else
799     {
800       as_bad ("unrecognized symbol type, ignored");
801       goto egress;
802     }
803   demand_empty_rest_of_line ();
804   *p = 0;
805   sym = symbol_find_or_make (name);
806   sym->bsym->flags |= type;
807 }
808
809 static void
810 obj_elf_ident ()
811 {
812   static segT comment_section;
813   segT old_section = now_seg;
814   int old_subsection = now_subseg;
815
816   if (!comment_section)
817     {
818       char *p;
819       comment_section = subseg_new (".comment", 0);
820       bfd_set_section_flags (stdoutput, comment_section, SEC_HAS_CONTENTS);
821       p = frag_more (1);
822       *p = 0;
823     }
824   else
825     subseg_set (comment_section, 0);
826   stringer (1);
827   subseg_set (old_section, old_subsection);
828 }
829
830 void 
831 elf_frob_file ()
832 {
833 #ifdef elf_tc_symbol
834   int i;
835
836   for (i = 0; i < stdoutput->symcount; i++)
837     elf_tc_symbol (stdoutput, (elf_symbol_type *) (stdoutput->outsymbols[i]), i + 1);
838 #endif
839 #ifdef elf_tc_final_processing
840   elf_tc_final_processing_hook ();
841 #endif
842
843   /* Finally, we must make any target-specific sections. */
844
845 #ifdef elf_tc_make_sections
846   elf_tc_make_sections (stdoutput, NULL);
847 #endif
848 }