Home | History | Annotate | Download | only in config
      1 /* coff object file format
      2    Copyright (C) 1989-2014 Free Software Foundation, Inc.
      3 
      4    This file is part of GAS.
      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 published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    GAS is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with GAS; see the file COPYING.  If not, write to the Free
     18    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19    02110-1301, USA.  */
     20 
     21 #define OBJ_HEADER "obj-coff.h"
     22 
     23 #include "as.h"
     24 #include "safe-ctype.h"
     25 #include "subsegs.h"
     26 #include "struc-symbol.h"
     27 
     28 #ifdef TE_PE
     29 #include "coff/pe.h"
     30 #endif
     31 
     32 #ifdef OBJ_XCOFF
     33 #include "coff/xcoff.h"
     34 #endif
     35 
     36 #define streq(a,b)     (strcmp ((a), (b)) == 0)
     37 #define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
     38 
     39 /* I think this is probably always correct.  */
     40 #ifndef KEEP_RELOC_INFO
     41 #define KEEP_RELOC_INFO
     42 #endif
     43 
     44 /* obj_coff_section will use this macro to set a new section's
     45    attributes when a directive has no valid flags or the "w" flag is
     46    used.  This default should be appropriate for most.  */
     47 #ifndef TC_COFF_SECTION_DEFAULT_ATTRIBUTES
     48 #define TC_COFF_SECTION_DEFAULT_ATTRIBUTES (SEC_LOAD | SEC_DATA)
     49 #endif
     50 
     51 /* This is used to hold the symbol built by a sequence of pseudo-ops
     52    from .def and .endef.  */
     53 static symbolS *def_symbol_in_progress;
     54 #ifdef TE_PE
     55 /* PE weak alternate symbols begin with this string.  */
     56 static const char weak_altprefix[] = ".weak.";
     57 #endif /* TE_PE */
     58 
     59 #include "obj-coff-seh.c"
     60 
     61 typedef struct
     62   {
     63     unsigned long chunk_size;
     64     unsigned long element_size;
     65     unsigned long size;
     66     char *data;
     67     unsigned long pointer;
     68   }
     69 stack;
     70 
     71 
     72 /* Stack stuff.  */
     74 
     75 static stack *
     76 stack_init (unsigned long chunk_size,
     77 	    unsigned long element_size)
     78 {
     79   stack *st;
     80 
     81   st = malloc (sizeof (* st));
     82   if (!st)
     83     return NULL;
     84   st->data = malloc (chunk_size);
     85   if (!st->data)
     86     {
     87       free (st);
     88       return NULL;
     89     }
     90   st->pointer = 0;
     91   st->size = chunk_size;
     92   st->chunk_size = chunk_size;
     93   st->element_size = element_size;
     94   return st;
     95 }
     96 
     97 static char *
     98 stack_push (stack *st, char *element)
     99 {
    100   if (st->pointer + st->element_size >= st->size)
    101     {
    102       st->size += st->chunk_size;
    103       if ((st->data = xrealloc (st->data, st->size)) == NULL)
    104 	return NULL;
    105     }
    106   memcpy (st->data + st->pointer, element, st->element_size);
    107   st->pointer += st->element_size;
    108   return st->data + st->pointer;
    109 }
    110 
    111 static char *
    112 stack_pop (stack *st)
    113 {
    114   if (st->pointer < st->element_size)
    115     {
    116       st->pointer = 0;
    117       return NULL;
    118     }
    119   st->pointer -= st->element_size;
    120   return st->data + st->pointer;
    121 }
    122 
    123 /* Maintain a list of the tagnames of the structures.  */
    125 
    126 static struct hash_control *tag_hash;
    127 
    128 static void
    129 tag_init (void)
    130 {
    131   tag_hash = hash_new ();
    132 }
    133 
    134 static void
    135 tag_insert (const char *name, symbolS *symbolP)
    136 {
    137   const char *error_string;
    138 
    139   if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
    140     as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
    141 	      name, error_string);
    142 }
    143 
    144 static symbolS *
    145 tag_find (char *name)
    146 {
    147   return (symbolS *) hash_find (tag_hash, name);
    148 }
    149 
    150 static symbolS *
    151 tag_find_or_make (char *name)
    152 {
    153   symbolS *symbolP;
    154 
    155   if ((symbolP = tag_find (name)) == NULL)
    156     {
    157       symbolP = symbol_new (name, undefined_section,
    158 			    0, &zero_address_frag);
    159 
    160       tag_insert (S_GET_NAME (symbolP), symbolP);
    161       symbol_table_insert (symbolP);
    162     }
    163 
    164   return symbolP;
    165 }
    166 
    167 /* We accept the .bss directive to set the section for backward
    168    compatibility with earlier versions of gas.  */
    169 
    170 static void
    171 obj_coff_bss (int ignore ATTRIBUTE_UNUSED)
    172 {
    173   if (*input_line_pointer == '\n')
    174     subseg_new (".bss", get_absolute_expression ());
    175   else
    176     s_lcomm (0);
    177 }
    178 
    179 #ifdef TE_PE
    180 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
    181    Parse a possible alignment value.  */
    182 
    183 static symbolS *
    184 obj_coff_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
    185 {
    186   addressT align = 0;
    187 
    188   if (*input_line_pointer == ',')
    189     {
    190       align = parse_align (0);
    191       if (align == (addressT) -1)
    192 	return NULL;
    193     }
    194 
    195   S_SET_VALUE (symbolP, size);
    196   S_SET_EXTERNAL (symbolP);
    197   S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
    198 
    199   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
    200 
    201   /* There is no S_SET_ALIGN (symbolP, align) in COFF/PE.
    202      Instead we must add a note to the .drectve section.  */
    203   if (align)
    204     {
    205       segT current_seg = now_seg;
    206       subsegT current_subseg = now_subseg;
    207       flagword oldflags;
    208       asection *sec;
    209       size_t pfxlen, numlen;
    210       char *frag;
    211       char numbuff[20];
    212 
    213       sec = subseg_new (".drectve", 0);
    214       oldflags = bfd_get_section_flags (stdoutput, sec);
    215       if (oldflags == SEC_NO_FLAGS)
    216 	{
    217 	  if (!bfd_set_section_flags (stdoutput, sec,
    218 		TC_COFF_SECTION_DEFAULT_ATTRIBUTES))
    219 	    as_warn (_("error setting flags for \"%s\": %s"),
    220 		bfd_section_name (stdoutput, sec),
    221 		bfd_errmsg (bfd_get_error ()));
    222 	}
    223 
    224       /* Emit a string.  Note no NUL-termination.  */
    225       pfxlen = strlen (" -aligncomm:") + 2 + strlen (S_GET_NAME (symbolP)) + 1;
    226       numlen = snprintf (numbuff, sizeof (numbuff), "%d", (int) align);
    227       frag = frag_more (pfxlen + numlen);
    228       (void) sprintf (frag, " -aligncomm:\"%s\",", S_GET_NAME (symbolP));
    229       memcpy (frag + pfxlen, numbuff, numlen);
    230       /* Restore original subseg. */
    231       subseg_set (current_seg, current_subseg);
    232     }
    233 
    234   return symbolP;
    235 }
    236 
    237 static void
    238 obj_coff_comm (int ignore ATTRIBUTE_UNUSED)
    239 {
    240   s_comm_internal (ignore, obj_coff_common_parse);
    241 }
    242 #endif /* TE_PE */
    243 
    244 #define GET_FILENAME_STRING(X) \
    245   ((char *) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
    246 
    247 /* @@ Ick.  */
    248 static segT
    249 fetch_coff_debug_section (void)
    250 {
    251   static segT debug_section;
    252 
    253   if (!debug_section)
    254     {
    255       const asymbol *s;
    256 
    257       s = bfd_make_debug_symbol (stdoutput, NULL, 0);
    258       gas_assert (s != 0);
    259       debug_section = s->section;
    260     }
    261   return debug_section;
    262 }
    263 
    264 void
    265 SA_SET_SYM_ENDNDX (symbolS *sym, symbolS *val)
    266 {
    267   combined_entry_type *entry, *p;
    268 
    269   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
    270   p = coffsymbol (symbol_get_bfdsym (val))->native;
    271   entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
    272   entry->fix_end = 1;
    273 }
    274 
    275 static void
    276 SA_SET_SYM_TAGNDX (symbolS *sym, symbolS *val)
    277 {
    278   combined_entry_type *entry, *p;
    279 
    280   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
    281   p = coffsymbol (symbol_get_bfdsym (val))->native;
    282   entry->u.auxent.x_sym.x_tagndx.p = p;
    283   entry->fix_tag = 1;
    284 }
    285 
    286 static int
    287 S_GET_DATA_TYPE (symbolS *sym)
    288 {
    289   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type;
    290 }
    291 
    292 int
    293 S_SET_DATA_TYPE (symbolS *sym, int val)
    294 {
    295   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type = val;
    296   return val;
    297 }
    298 
    299 int
    300 S_GET_STORAGE_CLASS (symbolS *sym)
    301 {
    302   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass;
    303 }
    304 
    305 int
    306 S_SET_STORAGE_CLASS (symbolS *sym, int val)
    307 {
    308   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass = val;
    309   return val;
    310 }
    311 
    312 /* Merge a debug symbol containing debug information into a normal symbol.  */
    313 
    314 static void
    315 c_symbol_merge (symbolS *debug, symbolS *normal)
    316 {
    317   S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
    318   S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
    319 
    320   if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
    321     /* Take the most we have.  */
    322     S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
    323 
    324   if (S_GET_NUMBER_AUXILIARY (debug) > 0)
    325     /* Move all the auxiliary information.  */
    326     memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug),
    327 	    (S_GET_NUMBER_AUXILIARY (debug)
    328 	     * sizeof (*SYM_AUXINFO (debug))));
    329 
    330   /* Move the debug flags.  */
    331   SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
    332 }
    333 
    334 void
    335 c_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED)
    336 {
    337   symbolS *symbolP;
    338 
    339   /* BFD converts filename to a .file symbol with an aux entry.  It
    340      also handles chaining.  */
    341   symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag);
    342 
    343   S_SET_STORAGE_CLASS (symbolP, C_FILE);
    344   S_SET_NUMBER_AUXILIARY (symbolP, 1);
    345 
    346   symbol_get_bfdsym (symbolP)->flags = BSF_DEBUGGING;
    347 
    348 #ifndef NO_LISTING
    349   {
    350     extern int listing;
    351 
    352     if (listing)
    353       listing_source_file (filename);
    354   }
    355 #endif
    356 
    357   /* Make sure that the symbol is first on the symbol chain.  */
    358   if (symbol_rootP != symbolP)
    359     {
    360       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
    361       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
    362     }
    363 }
    364 
    365 /* Line number handling.  */
    366 
    367 struct line_no
    368 {
    369   struct line_no *next;
    370   fragS *frag;
    371   alent l;
    372 };
    373 
    374 int coff_line_base;
    375 
    376 /* Symbol of last function, which we should hang line#s off of.  */
    377 static symbolS *line_fsym;
    378 
    379 #define in_function()		(line_fsym != 0)
    380 #define clear_function()	(line_fsym = 0)
    381 #define set_function(F)		(line_fsym = (F), coff_add_linesym (F))
    382 
    383 
    384 void
    386 coff_obj_symbol_new_hook (symbolS *symbolP)
    387 {
    388   long   sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
    389   char * s  = xmalloc (sz);
    390 
    391   memset (s, 0, sz);
    392   coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
    393   coffsymbol (symbol_get_bfdsym (symbolP))->native->is_sym = TRUE;
    394 
    395   S_SET_DATA_TYPE (symbolP, T_NULL);
    396   S_SET_STORAGE_CLASS (symbolP, 0);
    397   S_SET_NUMBER_AUXILIARY (symbolP, 0);
    398 
    399   if (S_IS_STRING (symbolP))
    400     SF_SET_STRING (symbolP);
    401 
    402   if (S_IS_LOCAL (symbolP))
    403     SF_SET_LOCAL (symbolP);
    404 }
    405 
    406 void
    407 coff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP)
    408 {
    409   long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
    410   combined_entry_type * s = xmalloc (sz);
    411 
    412   memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native, sz);
    413   coffsymbol (symbol_get_bfdsym (newsymP))->native = s;
    414 
    415   SF_SET (newsymP, SF_GET (orgsymP));
    416 }
    417 
    418 
    419 /* Handle .ln directives.  */
    421 
    422 static symbolS *current_lineno_sym;
    423 static struct line_no *line_nos;
    424 /* FIXME:  Blindly assume all .ln directives will be in the .text section.  */
    425 int coff_n_line_nos;
    426 
    427 static void
    428 add_lineno (fragS * frag, addressT offset, int num)
    429 {
    430   struct line_no * new_line = xmalloc (sizeof (* new_line));
    431 
    432   if (!current_lineno_sym)
    433     abort ();
    434 
    435 #ifndef OBJ_XCOFF
    436   /* The native aix assembler accepts negative line number.  */
    437 
    438   if (num <= 0)
    439     {
    440       /* Zero is used as an end marker in the file.  */
    441       as_warn (_("Line numbers must be positive integers\n"));
    442       num = 1;
    443     }
    444 #endif /* OBJ_XCOFF */
    445   new_line->next = line_nos;
    446   new_line->frag = frag;
    447   new_line->l.line_number = num;
    448   new_line->l.u.offset = offset;
    449   line_nos = new_line;
    450   coff_n_line_nos++;
    451 }
    452 
    453 void
    454 coff_add_linesym (symbolS *sym)
    455 {
    456   if (line_nos)
    457     {
    458       coffsymbol (symbol_get_bfdsym (current_lineno_sym))->lineno =
    459 	(alent *) line_nos;
    460       coff_n_line_nos++;
    461       line_nos = 0;
    462     }
    463   current_lineno_sym = sym;
    464 }
    465 
    466 static void
    467 obj_coff_ln (int appline)
    468 {
    469   int l;
    470 
    471   if (! appline && def_symbol_in_progress != NULL)
    472     {
    473       as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
    474       demand_empty_rest_of_line ();
    475       return;
    476     }
    477 
    478   l = get_absolute_expression ();
    479 
    480   /* If there is no lineno symbol, treat a .ln
    481      directive as if it were a .appline directive.  */
    482   if (appline || current_lineno_sym == NULL)
    483     new_logical_line ((char *) NULL, l - 1);
    484   else
    485     add_lineno (frag_now, frag_now_fix (), l);
    486 
    487 #ifndef NO_LISTING
    488   {
    489     extern int listing;
    490 
    491     if (listing)
    492       {
    493 	if (! appline)
    494 	  l += coff_line_base - 1;
    495 	listing_source_line (l);
    496       }
    497   }
    498 #endif
    499 
    500   demand_empty_rest_of_line ();
    501 }
    502 
    503 /* .loc is essentially the same as .ln; parse it for assembler
    504    compatibility.  */
    505 
    506 static void
    507 obj_coff_loc (int ignore ATTRIBUTE_UNUSED)
    508 {
    509   int lineno;
    510 
    511   /* FIXME: Why do we need this check?  We need it for ECOFF, but why
    512      do we need it for COFF?  */
    513   if (now_seg != text_section)
    514     {
    515       as_warn (_(".loc outside of .text"));
    516       demand_empty_rest_of_line ();
    517       return;
    518     }
    519 
    520   if (def_symbol_in_progress != NULL)
    521     {
    522       as_warn (_(".loc pseudo-op inside .def/.endef: ignored."));
    523       demand_empty_rest_of_line ();
    524       return;
    525     }
    526 
    527   /* Skip the file number.  */
    528   SKIP_WHITESPACE ();
    529   get_absolute_expression ();
    530   SKIP_WHITESPACE ();
    531 
    532   lineno = get_absolute_expression ();
    533 
    534 #ifndef NO_LISTING
    535   {
    536     extern int listing;
    537 
    538     if (listing)
    539       {
    540 	lineno += coff_line_base - 1;
    541 	listing_source_line (lineno);
    542       }
    543   }
    544 #endif
    545 
    546   demand_empty_rest_of_line ();
    547 
    548   add_lineno (frag_now, frag_now_fix (), lineno);
    549 }
    550 
    551 /* Handle the .ident pseudo-op.  */
    552 
    553 static void
    554 obj_coff_ident (int ignore ATTRIBUTE_UNUSED)
    555 {
    556   segT current_seg = now_seg;
    557   subsegT current_subseg = now_subseg;
    558 
    559 #ifdef TE_PE
    560   {
    561     segT sec;
    562 
    563     /* We could put it in .comment, but that creates an extra section
    564        that shouldn't be loaded into memory, which requires linker
    565        changes...  For now, until proven otherwise, use .rdata.  */
    566     sec = subseg_new (".rdata$zzz", 0);
    567     bfd_set_section_flags (stdoutput, sec,
    568 			   ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
    569 			    & bfd_applicable_section_flags (stdoutput)));
    570   }
    571 #else
    572   subseg_new (".comment", 0);
    573 #endif
    574 
    575   stringer (8 + 1);
    576   subseg_set (current_seg, current_subseg);
    577 }
    578 
    579 /* Handle .def directives.
    580 
    581    One might ask : why can't we symbol_new if the symbol does not
    582    already exist and fill it with debug information.  Because of
    583    the C_EFCN special symbol. It would clobber the value of the
    584    function symbol before we have a chance to notice that it is
    585    a C_EFCN. And a second reason is that the code is more clear this
    586    way. (at least I think it is :-).  */
    587 
    588 #define SKIP_SEMI_COLON()	while (*input_line_pointer++ != ';')
    589 #define SKIP_WHITESPACES()	while (*input_line_pointer == ' ' || \
    590 				       *input_line_pointer == '\t')  \
    591                                   input_line_pointer++;
    592 
    593 static void
    594 obj_coff_def (int what ATTRIBUTE_UNUSED)
    595 {
    596   char name_end;		/* Char after the end of name.  */
    597   char *symbol_name;		/* Name of the debug symbol.  */
    598   char *symbol_name_copy;	/* Temporary copy of the name.  */
    599   unsigned int symbol_name_length;
    600 
    601   if (def_symbol_in_progress != NULL)
    602     {
    603       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
    604       demand_empty_rest_of_line ();
    605       return;
    606     }
    607 
    608   SKIP_WHITESPACES ();
    609 
    610   symbol_name = input_line_pointer;
    611   name_end = get_symbol_end ();
    612   symbol_name_length = strlen (symbol_name);
    613   symbol_name_copy = xmalloc (symbol_name_length + 1);
    614   strcpy (symbol_name_copy, symbol_name);
    615 #ifdef tc_canonicalize_symbol_name
    616   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
    617 #endif
    618 
    619   /* Initialize the new symbol.  */
    620   def_symbol_in_progress = symbol_make (symbol_name_copy);
    621   symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
    622   S_SET_VALUE (def_symbol_in_progress, 0);
    623 
    624   if (S_IS_STRING (def_symbol_in_progress))
    625     SF_SET_STRING (def_symbol_in_progress);
    626 
    627   *input_line_pointer = name_end;
    628 
    629   demand_empty_rest_of_line ();
    630 }
    631 
    632 static void
    633 obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
    634 {
    635   symbolS *symbolP = NULL;
    636 
    637   if (def_symbol_in_progress == NULL)
    638     {
    639       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
    640       demand_empty_rest_of_line ();
    641       return;
    642     }
    643 
    644   /* Set the section number according to storage class.  */
    645   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
    646     {
    647     case C_STRTAG:
    648     case C_ENTAG:
    649     case C_UNTAG:
    650       SF_SET_TAG (def_symbol_in_progress);
    651       /* Fall through.  */
    652     case C_FILE:
    653     case C_TPDEF:
    654       SF_SET_DEBUG (def_symbol_in_progress);
    655       S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
    656       break;
    657 
    658     case C_EFCN:
    659       SF_SET_LOCAL (def_symbol_in_progress);	/* Do not emit this symbol.  */
    660       /* Fall through.  */
    661     case C_BLOCK:
    662       SF_SET_PROCESS (def_symbol_in_progress);	/* Will need processing before writing.  */
    663       /* Fall through.  */
    664     case C_FCN:
    665       {
    666 	const char *name;
    667 
    668 	S_SET_SEGMENT (def_symbol_in_progress, text_section);
    669 
    670 	name = S_GET_NAME (def_symbol_in_progress);
    671 	if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
    672 	  {
    673 	    switch (name[1])
    674 	      {
    675 	      case 'b':
    676 		/* .bf */
    677 		if (! in_function ())
    678 		  as_warn (_("`%s' symbol without preceding function"), name);
    679 		/* Will need relocating.  */
    680 		SF_SET_PROCESS (def_symbol_in_progress);
    681 		clear_function ();
    682 		break;
    683 #ifdef TE_PE
    684 	      case 'e':
    685 		/* .ef */
    686 		/* The MS compilers output the actual endline, not the
    687 		   function-relative one... we want to match without
    688 		   changing the assembler input.  */
    689 		SA_SET_SYM_LNNO (def_symbol_in_progress,
    690 				 (SA_GET_SYM_LNNO (def_symbol_in_progress)
    691 				  + coff_line_base));
    692 		break;
    693 #endif
    694 	      }
    695 	  }
    696       }
    697       break;
    698 
    699 #ifdef C_AUTOARG
    700     case C_AUTOARG:
    701 #endif /* C_AUTOARG */
    702     case C_AUTO:
    703     case C_REG:
    704     case C_ARG:
    705     case C_REGPARM:
    706     case C_FIELD:
    707 
    708     /* According to the COFF documentation:
    709 
    710        http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html
    711 
    712        A special section number (-2) marks symbolic debugging symbols,
    713        including structure/union/enumeration tag names, typedefs, and
    714        the name of the file. A section number of -1 indicates that the
    715        symbol has a value but is not relocatable. Examples of
    716        absolute-valued symbols include automatic and register variables,
    717        function arguments, and .eos symbols.
    718 
    719        But from Ian Lance Taylor:
    720 
    721        http://sources.redhat.com/ml/binutils/2000-08/msg00202.html
    722 
    723        the actual tools all marked them as section -1. So the GNU COFF
    724        assembler follows historical COFF assemblers.
    725 
    726        However, it causes problems for djgpp
    727 
    728        http://sources.redhat.com/ml/binutils/2000-08/msg00210.html
    729 
    730        By defining STRICTCOFF, a COFF port can make the assembler to
    731        follow the documented behavior.  */
    732 #ifdef STRICTCOFF
    733     case C_MOS:
    734     case C_MOE:
    735     case C_MOU:
    736     case C_EOS:
    737 #endif
    738       SF_SET_DEBUG (def_symbol_in_progress);
    739       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
    740       break;
    741 
    742 #ifndef STRICTCOFF
    743     case C_MOS:
    744     case C_MOE:
    745     case C_MOU:
    746     case C_EOS:
    747       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
    748       break;
    749 #endif
    750 
    751     case C_EXT:
    752     case C_WEAKEXT:
    753 #ifdef TE_PE
    754     case C_NT_WEAK:
    755 #endif
    756     case C_STAT:
    757     case C_LABEL:
    758       /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
    759       break;
    760 
    761     default:
    762     case C_USTATIC:
    763     case C_EXTDEF:
    764     case C_ULABEL:
    765       as_warn (_("unexpected storage class %d"),
    766 	       S_GET_STORAGE_CLASS (def_symbol_in_progress));
    767       break;
    768     }
    769 
    770   /* Now that we have built a debug symbol, try to find if we should
    771      merge with an existing symbol or not.  If a symbol is C_EFCN or
    772      absolute_section or untagged SEG_DEBUG it never merges.  We also
    773      don't merge labels, which are in a different namespace, nor
    774      symbols which have not yet been defined since they are typically
    775      unique, nor do we merge tags with non-tags.  */
    776 
    777   /* Two cases for functions.  Either debug followed by definition or
    778      definition followed by debug.  For definition first, we will
    779      merge the debug symbol into the definition.  For debug first, the
    780      lineno entry MUST point to the definition function or else it
    781      will point off into space when obj_crawl_symbol_chain() merges
    782      the debug symbol into the real symbol.  Therefor, let's presume
    783      the debug symbol is a real function reference.  */
    784 
    785   /* FIXME-SOON If for some reason the definition label/symbol is
    786      never seen, this will probably leave an undefined symbol at link
    787      time.  */
    788 
    789   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
    790       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
    791       || (streq (bfd_get_section_name (stdoutput,
    792 				       S_GET_SEGMENT (def_symbol_in_progress)),
    793 		 "*DEBUG*")
    794 	  && !SF_GET_TAG (def_symbol_in_progress))
    795       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
    796       || ! symbol_constant_p (def_symbol_in_progress)
    797       || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL
    798       || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
    799     {
    800       /* If it already is at the end of the symbol list, do nothing */
    801       if (def_symbol_in_progress != symbol_lastP)
    802 	{
    803 	  symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
    804 	  symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
    805 			 &symbol_lastP);
    806 	}
    807     }
    808   else
    809     {
    810       /* This symbol already exists, merge the newly created symbol
    811 	 into the old one.  This is not mandatory. The linker can
    812 	 handle duplicate symbols correctly. But I guess that it save
    813 	 a *lot* of space if the assembly file defines a lot of
    814 	 symbols. [loic]  */
    815 
    816       /* The debug entry (def_symbol_in_progress) is merged into the
    817 	 previous definition.  */
    818 
    819       c_symbol_merge (def_symbol_in_progress, symbolP);
    820       symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
    821 
    822       def_symbol_in_progress = symbolP;
    823 
    824       if (SF_GET_FUNCTION (def_symbol_in_progress)
    825 	  || SF_GET_TAG (def_symbol_in_progress)
    826 	  || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
    827 	{
    828 	  /* For functions, and tags, and static symbols, the symbol
    829 	     *must* be where the debug symbol appears.  Move the
    830 	     existing symbol to the current place.  */
    831 	  /* If it already is at the end of the symbol list, do nothing.  */
    832 	  if (def_symbol_in_progress != symbol_lastP)
    833 	    {
    834 	      symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
    835 	      symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
    836 	    }
    837 	}
    838     }
    839 
    840   if (SF_GET_TAG (def_symbol_in_progress))
    841     {
    842       symbolS *oldtag;
    843 
    844       oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress));
    845       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
    846 	tag_insert (S_GET_NAME (def_symbol_in_progress),
    847 		    def_symbol_in_progress);
    848     }
    849 
    850   if (SF_GET_FUNCTION (def_symbol_in_progress))
    851     {
    852       set_function (def_symbol_in_progress);
    853       SF_SET_PROCESS (def_symbol_in_progress);
    854 
    855       if (symbolP == NULL)
    856 	/* That is, if this is the first time we've seen the
    857 	   function.  */
    858 	symbol_table_insert (def_symbol_in_progress);
    859 
    860     }
    861 
    862   def_symbol_in_progress = NULL;
    863   demand_empty_rest_of_line ();
    864 }
    865 
    866 static void
    867 obj_coff_dim (int ignore ATTRIBUTE_UNUSED)
    868 {
    869   int d_index;
    870 
    871   if (def_symbol_in_progress == NULL)
    872     {
    873       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
    874       demand_empty_rest_of_line ();
    875       return;
    876     }
    877 
    878   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
    879 
    880   for (d_index = 0; d_index < DIMNUM; d_index++)
    881     {
    882       SKIP_WHITESPACES ();
    883       SA_SET_SYM_DIMEN (def_symbol_in_progress, d_index,
    884 			get_absolute_expression ());
    885 
    886       switch (*input_line_pointer)
    887 	{
    888 	case ',':
    889 	  input_line_pointer++;
    890 	  break;
    891 
    892 	default:
    893 	  as_warn (_("badly formed .dim directive ignored"));
    894 	  /* Fall through.  */
    895 	case '\n':
    896 	case ';':
    897 	  d_index = DIMNUM;
    898 	  break;
    899 	}
    900     }
    901 
    902   demand_empty_rest_of_line ();
    903 }
    904 
    905 static void
    906 obj_coff_line (int ignore ATTRIBUTE_UNUSED)
    907 {
    908   int this_base;
    909 
    910   if (def_symbol_in_progress == NULL)
    911     {
    912       /* Probably stabs-style line?  */
    913       obj_coff_ln (0);
    914       return;
    915     }
    916 
    917   this_base = get_absolute_expression ();
    918   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
    919     coff_line_base = this_base;
    920 
    921   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
    922   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
    923 
    924   demand_empty_rest_of_line ();
    925 
    926 #ifndef NO_LISTING
    927   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
    928     {
    929       extern int listing;
    930 
    931       if (listing)
    932 	listing_source_line ((unsigned int) this_base);
    933     }
    934 #endif
    935 }
    936 
    937 static void
    938 obj_coff_size (int ignore ATTRIBUTE_UNUSED)
    939 {
    940   if (def_symbol_in_progress == NULL)
    941     {
    942       as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
    943       demand_empty_rest_of_line ();
    944       return;
    945     }
    946 
    947   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
    948   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
    949   demand_empty_rest_of_line ();
    950 }
    951 
    952 static void
    953 obj_coff_scl (int ignore ATTRIBUTE_UNUSED)
    954 {
    955   if (def_symbol_in_progress == NULL)
    956     {
    957       as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
    958       demand_empty_rest_of_line ();
    959       return;
    960     }
    961 
    962   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
    963   demand_empty_rest_of_line ();
    964 }
    965 
    966 static void
    967 obj_coff_tag (int ignore ATTRIBUTE_UNUSED)
    968 {
    969   char *symbol_name;
    970   char name_end;
    971 
    972   if (def_symbol_in_progress == NULL)
    973     {
    974       as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
    975       demand_empty_rest_of_line ();
    976       return;
    977     }
    978 
    979   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
    980   symbol_name = input_line_pointer;
    981   name_end = get_symbol_end ();
    982 
    983 #ifdef tc_canonicalize_symbol_name
    984   symbol_name = tc_canonicalize_symbol_name (symbol_name);
    985 #endif
    986 
    987   /* Assume that the symbol referred to by .tag is always defined.
    988      This was a bad assumption.  I've added find_or_make. xoxorich.  */
    989   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
    990 		     tag_find_or_make (symbol_name));
    991   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
    992     as_warn (_("tag not found for .tag %s"), symbol_name);
    993 
    994   SF_SET_TAGGED (def_symbol_in_progress);
    995   *input_line_pointer = name_end;
    996 
    997   demand_empty_rest_of_line ();
    998 }
    999 
   1000 static void
   1001 obj_coff_type (int ignore ATTRIBUTE_UNUSED)
   1002 {
   1003   if (def_symbol_in_progress == NULL)
   1004     {
   1005       as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
   1006       demand_empty_rest_of_line ();
   1007       return;
   1008     }
   1009 
   1010   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
   1011 
   1012   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
   1013       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
   1014     SF_SET_FUNCTION (def_symbol_in_progress);
   1015 
   1016   demand_empty_rest_of_line ();
   1017 }
   1018 
   1019 static void
   1020 obj_coff_val (int ignore ATTRIBUTE_UNUSED)
   1021 {
   1022   if (def_symbol_in_progress == NULL)
   1023     {
   1024       as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
   1025       demand_empty_rest_of_line ();
   1026       return;
   1027     }
   1028 
   1029   if (is_name_beginner (*input_line_pointer))
   1030     {
   1031       char *symbol_name = input_line_pointer;
   1032       char name_end = get_symbol_end ();
   1033 
   1034 #ifdef tc_canonicalize_symbol_name
   1035   symbol_name = tc_canonicalize_symbol_name (symbol_name);
   1036 #endif
   1037       if (streq (symbol_name, "."))
   1038 	{
   1039 	  /* If the .val is != from the .def (e.g. statics).  */
   1040 	  symbol_set_frag (def_symbol_in_progress, frag_now);
   1041 	  S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
   1042 	}
   1043       else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name))
   1044 	{
   1045 	  expressionS exp;
   1046 
   1047 	  exp.X_op = O_symbol;
   1048 	  exp.X_add_symbol = symbol_find_or_make (symbol_name);
   1049 	  exp.X_op_symbol = NULL;
   1050 	  exp.X_add_number = 0;
   1051 	  symbol_set_value_expression (def_symbol_in_progress, &exp);
   1052 
   1053 	  /* If the segment is undefined when the forward reference is
   1054 	     resolved, then copy the segment id from the forward
   1055 	     symbol.  */
   1056 	  SF_SET_GET_SEGMENT (def_symbol_in_progress);
   1057 
   1058 	  /* FIXME: gcc can generate address expressions here in
   1059 	     unusual cases (search for "obscure" in sdbout.c).  We
   1060 	     just ignore the offset here, thus generating incorrect
   1061 	     debugging information.  We ignore the rest of the line
   1062 	     just below.  */
   1063 	}
   1064       /* Otherwise, it is the name of a non debug symbol and its value
   1065          will be calculated later.  */
   1066       *input_line_pointer = name_end;
   1067     }
   1068   else
   1069     {
   1070       S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
   1071     }
   1072 
   1073   demand_empty_rest_of_line ();
   1074 }
   1075 
   1076 #ifdef TE_PE
   1077 
   1078 /* Return nonzero if name begins with weak alternate symbol prefix.  */
   1079 
   1080 static int
   1081 weak_is_altname (const char * name)
   1082 {
   1083   return strneq (name, weak_altprefix, sizeof (weak_altprefix) - 1);
   1084 }
   1085 
   1086 /* Return the name of the alternate symbol
   1087    name corresponding to a weak symbol's name.  */
   1088 
   1089 static const char *
   1090 weak_name2altname (const char * name)
   1091 {
   1092   char *alt_name;
   1093 
   1094   alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name));
   1095   strcpy (alt_name, weak_altprefix);
   1096   return strcat (alt_name, name);
   1097 }
   1098 
   1099 /* Return the name of the weak symbol corresponding to an
   1100    alternate symbol.  */
   1101 
   1102 static const char *
   1103 weak_altname2name (const char * name)
   1104 {
   1105   gas_assert (weak_is_altname (name));
   1106   return xstrdup (name + 6);
   1107 }
   1108 
   1109 /* Make a weak symbol name unique by
   1110    appending the name of an external symbol.  */
   1111 
   1112 static const char *
   1113 weak_uniquify (const char * name)
   1114 {
   1115   char *ret;
   1116   const char * unique = "";
   1117 
   1118 #ifdef TE_PE
   1119   if (an_external_name != NULL)
   1120     unique = an_external_name;
   1121 #endif
   1122   gas_assert (weak_is_altname (name));
   1123 
   1124   ret = xmalloc (strlen (name) + strlen (unique) + 2);
   1125   strcpy (ret, name);
   1126   strcat (ret, ".");
   1127   strcat (ret, unique);
   1128   return ret;
   1129 }
   1130 
   1131 void
   1132 pecoff_obj_set_weak_hook (symbolS *symbolP)
   1133 {
   1134   symbolS *alternateP;
   1135 
   1136   /* See _Microsoft Portable Executable and Common Object
   1137      File Format Specification_, section 5.5.3.
   1138      Create a symbol representing the alternate value.
   1139      coff_frob_symbol will set the value of this symbol from
   1140      the value of the weak symbol itself.  */
   1141   S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
   1142   S_SET_NUMBER_AUXILIARY (symbolP, 1);
   1143   SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
   1144 
   1145   alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
   1146   S_SET_EXTERNAL (alternateP);
   1147   S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
   1148 
   1149   SA_SET_SYM_TAGNDX (symbolP, alternateP);
   1150 }
   1151 
   1152 void
   1153 pecoff_obj_clear_weak_hook (symbolS *symbolP)
   1154 {
   1155   symbolS *alternateP;
   1156 
   1157   S_SET_STORAGE_CLASS (symbolP, 0);
   1158   SA_SET_SYM_FSIZE (symbolP, 0);
   1159 
   1160   alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
   1161   S_CLEAR_EXTERNAL (alternateP);
   1162 }
   1163 
   1164 #endif  /* TE_PE */
   1165 
   1166 /* Handle .weak.  This is a GNU extension in formats other than PE. */
   1167 
   1168 static void
   1169 obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
   1170 {
   1171   char *name;
   1172   int c;
   1173   symbolS *symbolP;
   1174 
   1175   do
   1176     {
   1177       name = input_line_pointer;
   1178       c = get_symbol_end ();
   1179       if (*name == 0)
   1180 	{
   1181 	  as_warn (_("badly formed .weak directive ignored"));
   1182 	  ignore_rest_of_line ();
   1183 	  return;
   1184 	}
   1185       c = 0;
   1186       symbolP = symbol_find_or_make (name);
   1187       *input_line_pointer = c;
   1188       SKIP_WHITESPACE ();
   1189       S_SET_WEAK (symbolP);
   1190 
   1191       if (c == ',')
   1192 	{
   1193 	  input_line_pointer++;
   1194 	  SKIP_WHITESPACE ();
   1195 	  if (*input_line_pointer == '\n')
   1196 	    c = '\n';
   1197 	}
   1198 
   1199     }
   1200   while (c == ',');
   1201 
   1202   demand_empty_rest_of_line ();
   1203 }
   1204 
   1205 void
   1206 coff_obj_read_begin_hook (void)
   1207 {
   1208   /* These had better be the same.  Usually 18 bytes.  */
   1209   know (sizeof (SYMENT) == sizeof (AUXENT));
   1210   know (SYMESZ == AUXESZ);
   1211   tag_init ();
   1212 }
   1213 
   1214 symbolS *coff_last_function;
   1215 #ifndef OBJ_XCOFF
   1216 static symbolS *coff_last_bf;
   1217 #endif
   1218 
   1219 void
   1220 coff_frob_symbol (symbolS *symp, int *punt)
   1221 {
   1222   static symbolS *last_tagP;
   1223   static stack *block_stack;
   1224   static symbolS *set_end;
   1225   symbolS *next_set_end = NULL;
   1226 
   1227   if (symp == &abs_symbol)
   1228     {
   1229       *punt = 1;
   1230       return;
   1231     }
   1232 
   1233   if (current_lineno_sym)
   1234     coff_add_linesym (NULL);
   1235 
   1236   if (!block_stack)
   1237     block_stack = stack_init (512, sizeof (symbolS*));
   1238 
   1239 #ifdef TE_PE
   1240   if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
   1241       && ! S_IS_WEAK (symp)
   1242       && weak_is_altname (S_GET_NAME (symp)))
   1243     {
   1244       /* This is a weak alternate symbol.  All processing of
   1245 	 PECOFFweak symbols is done here, through the alternate.  */
   1246       symbolS *weakp = symbol_find_noref (weak_altname2name
   1247 					  (S_GET_NAME (symp)), 1);
   1248 
   1249       gas_assert (weakp);
   1250       gas_assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
   1251 
   1252       if (! S_IS_WEAK (weakp))
   1253 	{
   1254 	  /* The symbol was turned from weak to strong.  Discard altname.  */
   1255 	  *punt = 1;
   1256 	  return;
   1257 	}
   1258       else if (symbol_equated_p (weakp))
   1259 	{
   1260 	  /* The weak symbol has an alternate specified; symp is unneeded.  */
   1261 	  S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
   1262 	  SA_SET_SYM_TAGNDX (weakp,
   1263 	    symbol_get_value_expression (weakp)->X_add_symbol);
   1264 
   1265 	  S_CLEAR_EXTERNAL (symp);
   1266 	  *punt = 1;
   1267 	  return;
   1268 	}
   1269       else
   1270 	{
   1271 	  /* The weak symbol has been assigned an alternate value.
   1272              Copy this value to symp, and set symp as weakp's alternate.  */
   1273 	  if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
   1274 	    {
   1275 	      S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
   1276 	      S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
   1277 	    }
   1278 
   1279 	  if (S_IS_DEFINED (weakp))
   1280 	    {
   1281 	      /* This is a defined weak symbol.  Copy value information
   1282 	         from the weak symbol itself to the alternate symbol.  */
   1283 	      symbol_set_value_expression (symp,
   1284 					   symbol_get_value_expression (weakp));
   1285 	      symbol_set_frag (symp, symbol_get_frag (weakp));
   1286 	      S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
   1287 	    }
   1288 	  else
   1289 	    {
   1290 	      /* This is an undefined weak symbol.
   1291 		 Define the alternate symbol to zero.  */
   1292 	      S_SET_VALUE (symp, 0);
   1293 	      S_SET_SEGMENT (symp, absolute_section);
   1294 	    }
   1295 
   1296 	  S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
   1297 	  S_SET_STORAGE_CLASS (symp, C_EXT);
   1298 
   1299 	  S_SET_VALUE (weakp, 0);
   1300 	  S_SET_SEGMENT (weakp, undefined_section);
   1301 	}
   1302     }
   1303 #else /* TE_PE */
   1304   if (S_IS_WEAK (symp))
   1305     S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
   1306 #endif /* TE_PE */
   1307 
   1308   if (!S_IS_DEFINED (symp)
   1309       && !S_IS_WEAK (symp)
   1310       && S_GET_STORAGE_CLASS (symp) != C_STAT)
   1311     S_SET_STORAGE_CLASS (symp, C_EXT);
   1312 
   1313   if (!SF_GET_DEBUG (symp))
   1314     {
   1315       symbolS * real;
   1316 
   1317       if (!SF_GET_LOCAL (symp)
   1318 	  && !SF_GET_STATICS (symp)
   1319 	  && S_GET_STORAGE_CLASS (symp) != C_LABEL
   1320 	  && symbol_constant_p (symp)
   1321 	  && (real = symbol_find_noref (S_GET_NAME (symp), 1))
   1322 	  && S_GET_STORAGE_CLASS (real) == C_NULL
   1323 	  && real != symp)
   1324 	{
   1325 	  c_symbol_merge (symp, real);
   1326 	  *punt = 1;
   1327 	  return;
   1328 	}
   1329 
   1330       if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
   1331 	{
   1332 	  gas_assert (S_GET_VALUE (symp) == 0);
   1333 	  if (S_IS_WEAKREFD (symp))
   1334 	    *punt = 1;
   1335 	  else
   1336 	    S_SET_EXTERNAL (symp);
   1337 	}
   1338       else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
   1339 	{
   1340 	  if (S_GET_SEGMENT (symp) == text_section
   1341 	      && symp != seg_info (text_section)->sym)
   1342 	    S_SET_STORAGE_CLASS (symp, C_LABEL);
   1343 	  else
   1344 	    S_SET_STORAGE_CLASS (symp, C_STAT);
   1345 	}
   1346 
   1347       if (SF_GET_PROCESS (symp))
   1348 	{
   1349 	  if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
   1350 	    {
   1351 	      if (streq (S_GET_NAME (symp), ".bb"))
   1352 		stack_push (block_stack, (char *) &symp);
   1353 	      else
   1354 		{
   1355 		  symbolS *begin;
   1356 
   1357 		  begin = *(symbolS **) stack_pop (block_stack);
   1358 		  if (begin == 0)
   1359 		    as_warn (_("mismatched .eb"));
   1360 		  else
   1361 		    next_set_end = begin;
   1362 		}
   1363 	    }
   1364 
   1365 	  if (coff_last_function == 0 && SF_GET_FUNCTION (symp)
   1366 	      && S_IS_DEFINED (symp))
   1367 	    {
   1368 	      union internal_auxent *auxp;
   1369 
   1370 	      coff_last_function = symp;
   1371 	      if (S_GET_NUMBER_AUXILIARY (symp) < 1)
   1372 		S_SET_NUMBER_AUXILIARY (symp, 1);
   1373 	      auxp = SYM_AUXENT (symp);
   1374 	      memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
   1375 		      sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
   1376 	    }
   1377 
   1378 	  if (S_GET_STORAGE_CLASS (symp) == C_EFCN
   1379 	      && S_IS_DEFINED (symp))
   1380 	    {
   1381 	      if (coff_last_function == 0)
   1382 		as_fatal (_("C_EFCN symbol for %s out of scope"),
   1383 			  S_GET_NAME (symp));
   1384 	      SA_SET_SYM_FSIZE (coff_last_function,
   1385 				(long) (S_GET_VALUE (symp)
   1386 					- S_GET_VALUE (coff_last_function)));
   1387 	      next_set_end = coff_last_function;
   1388 	      coff_last_function = 0;
   1389 	    }
   1390 	}
   1391 
   1392       if (S_IS_EXTERNAL (symp))
   1393 	S_SET_STORAGE_CLASS (symp, C_EXT);
   1394       else if (SF_GET_LOCAL (symp))
   1395 	*punt = 1;
   1396 
   1397       if (SF_GET_FUNCTION (symp))
   1398 	symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
   1399     }
   1400 
   1401   /* Double check weak symbols.  */
   1402   if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
   1403     as_bad (_("Symbol `%s' can not be both weak and common"),
   1404 	    S_GET_NAME (symp));
   1405 
   1406   if (SF_GET_TAG (symp))
   1407     last_tagP = symp;
   1408   else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
   1409     next_set_end = last_tagP;
   1410 
   1411 #ifdef OBJ_XCOFF
   1412   /* This is pretty horrible, but we have to set *punt correctly in
   1413      order to call SA_SET_SYM_ENDNDX correctly.  */
   1414   if (! symbol_used_in_reloc_p (symp)
   1415       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
   1416 	  || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
   1417 	      && ! symbol_get_tc (symp)->output
   1418 	      && S_GET_STORAGE_CLASS (symp) != C_FILE)))
   1419     *punt = 1;
   1420 #endif
   1421 
   1422   if (set_end != (symbolS *) NULL
   1423       && ! *punt
   1424       && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
   1425 	  || (S_IS_DEFINED (symp)
   1426 	      && ! S_IS_COMMON (symp)
   1427 	      && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
   1428     {
   1429       SA_SET_SYM_ENDNDX (set_end, symp);
   1430       set_end = NULL;
   1431     }
   1432 
   1433   if (next_set_end != NULL)
   1434     {
   1435       if (set_end != NULL)
   1436 	as_warn (_("Warning: internal error: forgetting to set endndx of %s"),
   1437 		 S_GET_NAME (set_end));
   1438       set_end = next_set_end;
   1439     }
   1440 
   1441 #ifndef OBJ_XCOFF
   1442   if (! *punt
   1443       && S_GET_STORAGE_CLASS (symp) == C_FCN
   1444       && streq (S_GET_NAME (symp), ".bf"))
   1445     {
   1446       if (coff_last_bf != NULL)
   1447 	SA_SET_SYM_ENDNDX (coff_last_bf, symp);
   1448       coff_last_bf = symp;
   1449     }
   1450 #endif
   1451   if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
   1452     {
   1453       int i;
   1454       struct line_no *lptr;
   1455       alent *l;
   1456 
   1457       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
   1458       for (i = 0; lptr; lptr = lptr->next)
   1459 	i++;
   1460       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
   1461 
   1462       /* We need i entries for line numbers, plus 1 for the first
   1463 	 entry which BFD will override, plus 1 for the last zero
   1464 	 entry (a marker for BFD).  */
   1465       l = xmalloc ((i + 2) * sizeof (* l));
   1466       coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
   1467       l[i + 1].line_number = 0;
   1468       l[i + 1].u.sym = NULL;
   1469       for (; i > 0; i--)
   1470 	{
   1471 	  if (lptr->frag)
   1472 	    lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
   1473 	  l[i] = lptr->l;
   1474 	  lptr = lptr->next;
   1475 	}
   1476     }
   1477 }
   1478 
   1479 void
   1480 coff_adjust_section_syms (bfd *abfd ATTRIBUTE_UNUSED,
   1481 			  asection *sec,
   1482 			  void * x ATTRIBUTE_UNUSED)
   1483 {
   1484   symbolS *secsym;
   1485   segment_info_type *seginfo = seg_info (sec);
   1486   int nlnno, nrelocs = 0;
   1487 
   1488   /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
   1489      tc-ppc.c.  Do not get confused by it.  */
   1490   if (seginfo == NULL)
   1491     return;
   1492 
   1493   if (streq (sec->name, ".text"))
   1494     nlnno = coff_n_line_nos;
   1495   else
   1496     nlnno = 0;
   1497   {
   1498     /* @@ Hope that none of the fixups expand to more than one reloc
   1499        entry...  */
   1500     fixS *fixp = seginfo->fix_root;
   1501     while (fixp)
   1502       {
   1503 	if (! fixp->fx_done)
   1504 	  nrelocs++;
   1505 	fixp = fixp->fx_next;
   1506       }
   1507   }
   1508   if (bfd_get_section_size (sec) == 0
   1509       && nrelocs == 0
   1510       && nlnno == 0
   1511       && sec != text_section
   1512       && sec != data_section
   1513       && sec != bss_section)
   1514     return;
   1515 
   1516   secsym = section_symbol (sec);
   1517   /* This is an estimate; we'll plug in the real value using
   1518      SET_SECTION_RELOCS later */
   1519   SA_SET_SCN_NRELOC (secsym, nrelocs);
   1520   SA_SET_SCN_NLINNO (secsym, nlnno);
   1521 }
   1522 
   1523 void
   1524 coff_frob_file_after_relocs (void)
   1525 {
   1526   bfd_map_over_sections (stdoutput, coff_adjust_section_syms, NULL);
   1527 }
   1528 
   1529 /* Implement the .section pseudo op:
   1530   	.section name {, "flags"}
   1531                   ^         ^
   1532                   |         +--- optional flags: 'b' for bss
   1533                   |                              'i' for info
   1534                   +-- section name               'l' for lib
   1535                                                  'n' for noload
   1536                                                  'o' for over
   1537                                                  'w' for data
   1538   						 'd' (apparently m88k for data)
   1539 						 'e' for exclude
   1540                                                  'x' for text
   1541   						 'r' for read-only data
   1542   						 's' for shared data (PE)
   1543 						 'y' for noread
   1544 					   '0' - '9' for power-of-two alignment (GNU extension).
   1545    But if the argument is not a quoted string, treat it as a
   1546    subsegment number.
   1547 
   1548    Note the 'a' flag is silently ignored.  This allows the same
   1549    .section directive to be parsed in both ELF and COFF formats.  */
   1550 
   1551 void
   1552 obj_coff_section (int ignore ATTRIBUTE_UNUSED)
   1553 {
   1554   /* Strip out the section name.  */
   1555   char *section_name;
   1556   char c;
   1557   int alignment = -1;
   1558   char *name;
   1559   unsigned int exp;
   1560   flagword flags, oldflags;
   1561   asection *sec;
   1562 
   1563   if (flag_mri)
   1564     {
   1565       char type;
   1566 
   1567       s_mri_sect (&type);
   1568       return;
   1569     }
   1570 
   1571   section_name = input_line_pointer;
   1572   c = get_symbol_end ();
   1573 
   1574   name = xmalloc (input_line_pointer - section_name + 1);
   1575   strcpy (name, section_name);
   1576 
   1577   *input_line_pointer = c;
   1578 
   1579   SKIP_WHITESPACE ();
   1580 
   1581   exp = 0;
   1582   flags = SEC_NO_FLAGS;
   1583 
   1584   if (*input_line_pointer == ',')
   1585     {
   1586       ++input_line_pointer;
   1587       SKIP_WHITESPACE ();
   1588       if (*input_line_pointer != '"')
   1589 	exp = get_absolute_expression ();
   1590       else
   1591 	{
   1592 	  unsigned char attr;
   1593 	  int readonly_removed = 0;
   1594 	  int load_removed = 0;
   1595 
   1596 	  while (attr = *++input_line_pointer,
   1597 		 attr != '"'
   1598 		 && ! is_end_of_line[attr])
   1599 	    {
   1600 	      if (ISDIGIT (attr))
   1601 		{
   1602 		  alignment = attr - '0';
   1603 		  continue;
   1604 		}
   1605 	      switch (attr)
   1606 		{
   1607 		case 'e':
   1608 		  /* Exclude section from linking.  */
   1609 		  flags |= SEC_EXCLUDE;
   1610 		  break;
   1611 
   1612 		case 'b':
   1613 		  /* Uninitialised data section.  */
   1614 		  flags |= SEC_ALLOC;
   1615 		  flags &=~ SEC_LOAD;
   1616 		  break;
   1617 
   1618 		case 'n':
   1619 		  /* Section not loaded.  */
   1620 		  flags &=~ SEC_LOAD;
   1621 		  flags |= SEC_NEVER_LOAD;
   1622 		  load_removed = 1;
   1623 		  break;
   1624 
   1625 		case 's':
   1626 		  /* Shared section.  */
   1627 		  flags |= SEC_COFF_SHARED;
   1628 		  /* Fall through.  */
   1629 		case 'd':
   1630 		  /* Data section.  */
   1631 		  flags |= SEC_DATA;
   1632 		  if (! load_removed)
   1633 		    flags |= SEC_LOAD;
   1634 		  flags &=~ SEC_READONLY;
   1635 		  break;
   1636 
   1637 		case 'w':
   1638 		  /* Writable section.  */
   1639 		  flags &=~ SEC_READONLY;
   1640 		  readonly_removed = 1;
   1641 		  break;
   1642 
   1643 		case 'a':
   1644 		  /* Ignore.  Here for compatibility with ELF.  */
   1645 		  break;
   1646 
   1647 		case 'r': /* Read-only section.  Implies a data section.  */
   1648 		  readonly_removed = 0;
   1649 		  /* Fall through.  */
   1650 		case 'x': /* Executable section.  */
   1651 		  /* If we are setting the 'x' attribute or if the 'r'
   1652 		     attribute is being used to restore the readonly status
   1653 		     of a code section (eg "wxr") then set the SEC_CODE flag,
   1654 		     otherwise set the SEC_DATA flag.  */
   1655 		  flags |= (attr == 'x' || (flags & SEC_CODE) ? SEC_CODE : SEC_DATA);
   1656 		  if (! load_removed)
   1657 		    flags |= SEC_LOAD;
   1658 		  /* Note - the READONLY flag is set here, even for the 'x'
   1659 		     attribute in order to be compatible with the MSVC
   1660 		     linker.  */
   1661 		  if (! readonly_removed)
   1662 		    flags |= SEC_READONLY;
   1663 		  break;
   1664 
   1665 		case 'y':
   1666 		  flags |= SEC_COFF_NOREAD | SEC_READONLY;
   1667 		  break;
   1668 
   1669 		case 'i': /* STYP_INFO */
   1670 		case 'l': /* STYP_LIB */
   1671 		case 'o': /* STYP_OVER */
   1672 		  as_warn (_("unsupported section attribute '%c'"), attr);
   1673 		  break;
   1674 
   1675 		default:
   1676 		  as_warn (_("unknown section attribute '%c'"), attr);
   1677 		  break;
   1678 		}
   1679 	    }
   1680 	  if (attr == '"')
   1681 	    ++input_line_pointer;
   1682 	}
   1683     }
   1684 
   1685   sec = subseg_new (name, (subsegT) exp);
   1686 
   1687   if (alignment >= 0)
   1688     sec->alignment_power = alignment;
   1689 
   1690   oldflags = bfd_get_section_flags (stdoutput, sec);
   1691   if (oldflags == SEC_NO_FLAGS)
   1692     {
   1693       /* Set section flags for a new section just created by subseg_new.
   1694          Provide a default if no flags were parsed.  */
   1695       if (flags == SEC_NO_FLAGS)
   1696 	flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;
   1697 
   1698 #ifdef COFF_LONG_SECTION_NAMES
   1699       /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce
   1700          sections so adjust_reloc_syms in write.c will correctly handle
   1701          relocs which refer to non-local symbols in these sections.  */
   1702       if (strneq (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1))
   1703 	flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
   1704 #endif
   1705 
   1706       if (! bfd_set_section_flags (stdoutput, sec, flags))
   1707 	as_warn (_("error setting flags for \"%s\": %s"),
   1708 		 bfd_section_name (stdoutput, sec),
   1709 		 bfd_errmsg (bfd_get_error ()));
   1710     }
   1711   else if (flags != SEC_NO_FLAGS)
   1712     {
   1713       /* This section's attributes have already been set.  Warn if the
   1714          attributes don't match.  */
   1715       flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
   1716 			     | SEC_DATA | SEC_COFF_SHARED | SEC_NEVER_LOAD
   1717 			     | SEC_COFF_NOREAD);
   1718       if ((flags ^ oldflags) & matchflags)
   1719 	as_warn (_("Ignoring changed section attributes for %s"), name);
   1720     }
   1721 
   1722   demand_empty_rest_of_line ();
   1723 }
   1724 
   1725 void
   1726 coff_adjust_symtab (void)
   1727 {
   1728   if (symbol_rootP == NULL
   1729       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
   1730     c_dot_file_symbol ("fake", 0);
   1731 }
   1732 
   1733 void
   1734 coff_frob_section (segT sec)
   1735 {
   1736   segT strsec;
   1737   char *p;
   1738   fragS *fragp;
   1739   bfd_vma n_entries;
   1740 
   1741   /* The COFF back end in BFD requires that all section sizes be
   1742      rounded up to multiples of the corresponding section alignments,
   1743      supposedly because standard COFF has no other way of encoding alignment
   1744      for sections.  If your COFF flavor has a different way of encoding
   1745      section alignment, then skip this step, as TICOFF does.  */
   1746   bfd_vma size = bfd_get_section_size (sec);
   1747 #if !defined(TICOFF)
   1748   bfd_vma align_power = (bfd_vma) sec->alignment_power + OCTETS_PER_BYTE_POWER;
   1749   bfd_vma mask = ((bfd_vma) 1 << align_power) - 1;
   1750 
   1751   if (size & mask)
   1752     {
   1753       bfd_vma new_size;
   1754       fragS *last;
   1755 
   1756       new_size = (size + mask) & ~mask;
   1757       bfd_set_section_size (stdoutput, sec, new_size);
   1758 
   1759       /* If the size had to be rounded up, add some padding in
   1760          the last non-empty frag.  */
   1761       fragp = seg_info (sec)->frchainP->frch_root;
   1762       last = seg_info (sec)->frchainP->frch_last;
   1763       while (fragp->fr_next != last)
   1764 	fragp = fragp->fr_next;
   1765       last->fr_address = size;
   1766       fragp->fr_offset += new_size - size;
   1767     }
   1768 #endif
   1769 
   1770   /* If the section size is non-zero, the section symbol needs an aux
   1771      entry associated with it, indicating the size.  We don't know
   1772      all the values yet; coff_frob_symbol will fill them in later.  */
   1773 #ifndef TICOFF
   1774   if (size != 0
   1775       || sec == text_section
   1776       || sec == data_section
   1777       || sec == bss_section)
   1778 #endif
   1779     {
   1780       symbolS *secsym = section_symbol (sec);
   1781       unsigned char sclass = C_STAT;
   1782 
   1783 #ifdef OBJ_XCOFF
   1784       if (bfd_get_section_flags (stdoutput, sec) & SEC_DEBUGGING)
   1785         sclass = C_DWARF;
   1786 #endif
   1787       S_SET_STORAGE_CLASS (secsym, sclass);
   1788       S_SET_NUMBER_AUXILIARY (secsym, 1);
   1789       SF_SET_STATICS (secsym);
   1790       SA_SET_SCN_SCNLEN (secsym, size);
   1791     }
   1792   /* FIXME: These should be in a "stabs.h" file, or maybe as.h.  */
   1793 #ifndef STAB_SECTION_NAME
   1794 #define STAB_SECTION_NAME ".stab"
   1795 #endif
   1796 #ifndef STAB_STRING_SECTION_NAME
   1797 #define STAB_STRING_SECTION_NAME ".stabstr"
   1798 #endif
   1799   if (! streq (STAB_STRING_SECTION_NAME, sec->name))
   1800     return;
   1801 
   1802   strsec = sec;
   1803   sec = subseg_get (STAB_SECTION_NAME, 0);
   1804   /* size is already rounded up, since other section will be listed first */
   1805   size = bfd_get_section_size (strsec);
   1806 
   1807   n_entries = bfd_get_section_size (sec) / 12 - 1;
   1808 
   1809   /* Find first non-empty frag.  It should be large enough.  */
   1810   fragp = seg_info (sec)->frchainP->frch_root;
   1811   while (fragp && fragp->fr_fix == 0)
   1812     fragp = fragp->fr_next;
   1813   gas_assert (fragp != 0 && fragp->fr_fix >= 12);
   1814 
   1815   /* Store the values.  */
   1816   p = fragp->fr_literal;
   1817   bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
   1818   bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
   1819 }
   1820 
   1821 void
   1822 obj_coff_init_stab_section (segT seg)
   1823 {
   1824   char *file;
   1825   char *p;
   1826   char *stabstr_name;
   1827   unsigned int stroff;
   1828 
   1829   /* Make space for this first symbol.  */
   1830   p = frag_more (12);
   1831   /* Zero it out.  */
   1832   memset (p, 0, 12);
   1833   as_where (&file, (unsigned int *) NULL);
   1834   stabstr_name = xmalloc (strlen (seg->name) + 4);
   1835   strcpy (stabstr_name, seg->name);
   1836   strcat (stabstr_name, "str");
   1837   stroff = get_stab_string_offset (file, stabstr_name);
   1838   know (stroff == 1);
   1839   md_number_to_chars (p, stroff, 4);
   1840 }
   1841 
   1842 #ifdef DEBUG
   1843 const char * s_get_name (symbolS *);
   1844 
   1845 const char *
   1846 s_get_name (symbolS *s)
   1847 {
   1848   return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
   1849 }
   1850 
   1851 void symbol_dump (void);
   1852 
   1853 void
   1854 symbol_dump (void)
   1855 {
   1856   symbolS *symbolP;
   1857 
   1858   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
   1859     printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
   1860 	    (unsigned long) symbolP,
   1861 	    S_GET_NAME (symbolP),
   1862 	    (long) S_GET_DATA_TYPE (symbolP),
   1863 	    S_GET_STORAGE_CLASS (symbolP),
   1864 	    (int) S_GET_SEGMENT (symbolP));
   1865 }
   1866 
   1867 #endif /* DEBUG */
   1868 
   1869 const pseudo_typeS coff_pseudo_table[] =
   1870 {
   1871   {"ABORT", s_abort, 0},
   1872   {"appline", obj_coff_ln, 1},
   1873   /* We accept the .bss directive for backward compatibility with
   1874      earlier versions of gas.  */
   1875   {"bss", obj_coff_bss, 0},
   1876 #ifdef TE_PE
   1877   /* PE provides an enhanced version of .comm with alignment.  */
   1878   {"comm", obj_coff_comm, 0},
   1879 #endif /* TE_PE */
   1880   {"def", obj_coff_def, 0},
   1881   {"dim", obj_coff_dim, 0},
   1882   {"endef", obj_coff_endef, 0},
   1883   {"ident", obj_coff_ident, 0},
   1884   {"line", obj_coff_line, 0},
   1885   {"ln", obj_coff_ln, 0},
   1886   {"scl", obj_coff_scl, 0},
   1887   {"sect", obj_coff_section, 0},
   1888   {"sect.s", obj_coff_section, 0},
   1889   {"section", obj_coff_section, 0},
   1890   {"section.s", obj_coff_section, 0},
   1891   /* FIXME: We ignore the MRI short attribute.  */
   1892   {"size", obj_coff_size, 0},
   1893   {"tag", obj_coff_tag, 0},
   1894   {"type", obj_coff_type, 0},
   1895   {"val", obj_coff_val, 0},
   1896   {"version", s_ignore, 0},
   1897   {"loc", obj_coff_loc, 0},
   1898   {"optim", s_ignore, 0},	/* For sun386i cc (?) */
   1899   {"weak", obj_coff_weak, 0},
   1900 #if defined TC_TIC4X
   1901   /* The tic4x uses sdef instead of def.  */
   1902   {"sdef", obj_coff_def, 0},
   1903 #endif
   1904 #if defined(SEH_CMDS)
   1905   SEH_CMDS
   1906 #endif
   1907   {NULL, NULL, 0}
   1908 };
   1909 
   1910 
   1912 /* Support for a COFF emulation.  */
   1913 
   1914 static void
   1915 coff_pop_insert (void)
   1916 {
   1917   pop_insert (coff_pseudo_table);
   1918 }
   1919 
   1920 static int
   1921 coff_separate_stab_sections (void)
   1922 {
   1923   return 1;
   1924 }
   1925 
   1926 const struct format_ops coff_format_ops =
   1927 {
   1928   bfd_target_coff_flavour,
   1929   0,	/* dfl_leading_underscore */
   1930   1,	/* emit_section_symbols */
   1931   0,    /* begin */
   1932   c_dot_file_symbol,
   1933   coff_frob_symbol,
   1934   0,	/* frob_file */
   1935   0,	/* frob_file_before_adjust */
   1936   0,	/* frob_file_before_fix */
   1937   coff_frob_file_after_relocs,
   1938   0,	/* s_get_size */
   1939   0,	/* s_set_size */
   1940   0,	/* s_get_align */
   1941   0,	/* s_set_align */
   1942   0,	/* s_get_other */
   1943   0,	/* s_set_other */
   1944   0,	/* s_get_desc */
   1945   0,	/* s_set_desc */
   1946   0,	/* s_get_type */
   1947   0,	/* s_set_type */
   1948   0,	/* copy_symbol_attributes */
   1949   0,	/* generate_asm_lineno */
   1950   0,	/* process_stab */
   1951   coff_separate_stab_sections,
   1952   obj_coff_init_stab_section,
   1953   0,	/* sec_sym_ok_for_reloc */
   1954   coff_pop_insert,
   1955   0,	/* ecoff_set_ext */
   1956   coff_obj_read_begin_hook,
   1957   coff_obj_symbol_new_hook,
   1958   coff_obj_symbol_clone_hook,
   1959   coff_adjust_symtab
   1960 };
   1961