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