Back to index

cell-binutils  2.17cvs20070401
obj-coff.c
Go to the documentation of this file.
00001 /* coff object file format
00002    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
00003    1999, 2000, 2001, 2002, 2003, 2004, 2005
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GAS.
00007 
00008    GAS is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2, or (at your option)
00011    any later version.
00012 
00013    GAS is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with GAS; see the file COPYING.  If not, write to the Free
00020    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 #define OBJ_HEADER "obj-coff.h"
00024 
00025 #include "as.h"
00026 #include "obstack.h"
00027 #include "subsegs.h"
00028 
00029 #ifdef TE_PE
00030 #include "coff/pe.h"
00031 #endif
00032 
00033 #define streq(a,b)     (strcmp ((a), (b)) == 0)
00034 #define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
00035 
00036 /* I think this is probably always correct.  */
00037 #ifndef KEEP_RELOC_INFO
00038 #define KEEP_RELOC_INFO
00039 #endif
00040 
00041 /* obj_coff_section will use this macro to set a new section's
00042    attributes when a directive has no valid flags or the "w" flag is
00043    used.  This default should be appropriate for most.  */
00044 #ifndef TC_COFF_SECTION_DEFAULT_ATTRIBUTES
00045 #define TC_COFF_SECTION_DEFAULT_ATTRIBUTES (SEC_LOAD | SEC_DATA)
00046 #endif
00047 
00048 /* This is used to hold the symbol built by a sequence of pseudo-ops
00049    from .def and .endef.  */
00050 static symbolS *def_symbol_in_progress;
00051 #ifdef TE_PE
00052 /* PE weak alternate symbols begin with this string.  */
00053 static const char weak_altprefix[] = ".weak.";
00054 #endif /* TE_PE */
00055 
00056 typedef struct
00057   {
00058     unsigned long chunk_size;
00059     unsigned long element_size;
00060     unsigned long size;
00061     char *data;
00062     unsigned long pointer;
00063   }
00064 stack;
00065 
00066 
00067 /* Stack stuff.  */
00068 
00069 static stack *
00070 stack_init (unsigned long chunk_size,
00071            unsigned long element_size)
00072 {
00073   stack *st;
00074 
00075   st = malloc (sizeof (* st));
00076   if (!st)
00077     return NULL;
00078   st->data = malloc (chunk_size);
00079   if (!st->data)
00080     {
00081       free (st);
00082       return NULL;
00083     }
00084   st->pointer = 0;
00085   st->size = chunk_size;
00086   st->chunk_size = chunk_size;
00087   st->element_size = element_size;
00088   return st;
00089 }
00090 
00091 static char *
00092 stack_push (stack *st, char *element)
00093 {
00094   if (st->pointer + st->element_size >= st->size)
00095     {
00096       st->size += st->chunk_size;
00097       if ((st->data = xrealloc (st->data, st->size)) == NULL)
00098        return NULL;
00099     }
00100   memcpy (st->data + st->pointer, element, st->element_size);
00101   st->pointer += st->element_size;
00102   return st->data + st->pointer;
00103 }
00104 
00105 static char *
00106 stack_pop (stack *st)
00107 {
00108   if (st->pointer < st->element_size)
00109     {
00110       st->pointer = 0;
00111       return NULL;
00112     }
00113   st->pointer -= st->element_size;
00114   return st->data + st->pointer;
00115 }
00116 
00117 /* Maintain a list of the tagnames of the structures.  */
00118 
00119 static struct hash_control *tag_hash;
00120 
00121 static void
00122 tag_init (void)
00123 {
00124   tag_hash = hash_new ();
00125 }
00126 
00127 static void
00128 tag_insert (const char *name, symbolS *symbolP)
00129 {
00130   const char *error_string;
00131 
00132   if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
00133     as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
00134              name, error_string);
00135 }
00136 
00137 static symbolS *
00138 tag_find (char *name)
00139 {
00140   return (symbolS *) hash_find (tag_hash, name);
00141 }
00142 
00143 static symbolS *
00144 tag_find_or_make (char *name)
00145 {
00146   symbolS *symbolP;
00147 
00148   if ((symbolP = tag_find (name)) == NULL)
00149     {
00150       symbolP = symbol_new (name, undefined_section,
00151                          0, &zero_address_frag);
00152 
00153       tag_insert (S_GET_NAME (symbolP), symbolP);
00154       symbol_table_insert (symbolP);
00155     }
00156 
00157   return symbolP;
00158 }
00159 
00160 /* We accept the .bss directive to set the section for backward
00161    compatibility with earlier versions of gas.  */
00162 
00163 static void
00164 obj_coff_bss (int ignore ATTRIBUTE_UNUSED)
00165 {
00166   if (*input_line_pointer == '\n')
00167     subseg_new (".bss", get_absolute_expression ());
00168   else
00169     s_lcomm (0);
00170 }
00171 
00172 #define GET_FILENAME_STRING(X) \
00173   ((char *) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
00174 
00175 /* @@ Ick.  */
00176 static segT
00177 fetch_coff_debug_section (void)
00178 {
00179   static segT debug_section;
00180 
00181   if (!debug_section)
00182     {
00183       const asymbol *s;
00184 
00185       s = bfd_make_debug_symbol (stdoutput, NULL, 0);
00186       assert (s != 0);
00187       debug_section = s->section;
00188     }
00189   return debug_section;
00190 }
00191 
00192 void
00193 SA_SET_SYM_ENDNDX (symbolS *sym, symbolS *val)
00194 {
00195   combined_entry_type *entry, *p;
00196 
00197   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
00198   p = coffsymbol (symbol_get_bfdsym (val))->native;
00199   entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
00200   entry->fix_end = 1;
00201 }
00202 
00203 static void
00204 SA_SET_SYM_TAGNDX (symbolS *sym, symbolS *val)
00205 {
00206   combined_entry_type *entry, *p;
00207 
00208   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
00209   p = coffsymbol (symbol_get_bfdsym (val))->native;
00210   entry->u.auxent.x_sym.x_tagndx.p = p;
00211   entry->fix_tag = 1;
00212 }
00213 
00214 static int
00215 S_GET_DATA_TYPE (symbolS *sym)
00216 {
00217   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type;
00218 }
00219 
00220 int
00221 S_SET_DATA_TYPE (symbolS *sym, int val)
00222 {
00223   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type = val;
00224   return val;
00225 }
00226 
00227 int
00228 S_GET_STORAGE_CLASS (symbolS *sym)
00229 {
00230   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass;
00231 }
00232 
00233 int
00234 S_SET_STORAGE_CLASS (symbolS *sym, int val)
00235 {
00236   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass = val;
00237   return val;
00238 }
00239 
00240 /* Merge a debug symbol containing debug information into a normal symbol.  */
00241 
00242 static void
00243 c_symbol_merge (symbolS *debug, symbolS *normal)
00244 {
00245   S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
00246   S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
00247 
00248   if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
00249     /* Take the most we have.  */
00250     S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
00251 
00252   if (S_GET_NUMBER_AUXILIARY (debug) > 0)
00253     /* Move all the auxiliary information.  */
00254     memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug),
00255            (S_GET_NUMBER_AUXILIARY (debug)
00256             * sizeof (*SYM_AUXINFO (debug))));
00257 
00258   /* Move the debug flags.  */
00259   SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
00260 }
00261 
00262 void
00263 c_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED)
00264 {
00265   symbolS *symbolP;
00266 
00267   /* BFD converts filename to a .file symbol with an aux entry.  It
00268      also handles chaining.  */
00269   symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag);
00270 
00271   S_SET_STORAGE_CLASS (symbolP, C_FILE);
00272   S_SET_NUMBER_AUXILIARY (symbolP, 1);
00273 
00274   symbol_get_bfdsym (symbolP)->flags = BSF_DEBUGGING;
00275 
00276 #ifndef NO_LISTING
00277   {
00278     extern int listing;
00279 
00280     if (listing)
00281       listing_source_file (filename);
00282   }
00283 #endif
00284 
00285   /* Make sure that the symbol is first on the symbol chain.  */
00286   if (symbol_rootP != symbolP)
00287     {
00288       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
00289       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
00290     }
00291 }
00292 
00293 /* Line number handling.  */
00294 
00295 struct line_no
00296 {
00297   struct line_no *next;
00298   fragS *frag;
00299   alent l;
00300 };
00301 
00302 int coff_line_base;
00303 
00304 /* Symbol of last function, which we should hang line#s off of.  */
00305 static symbolS *line_fsym;
00306 
00307 #define in_function()              (line_fsym != 0)
00308 #define clear_function()    (line_fsym = 0)
00309 #define set_function(F)            (line_fsym = (F), coff_add_linesym (F))
00310 
00311 
00312 void
00313 coff_obj_symbol_new_hook (symbolS *symbolP)
00314 {
00315   long   sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
00316   char * s  = xmalloc (sz);
00317 
00318   memset (s, 0, sz);
00319   coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
00320 
00321   S_SET_DATA_TYPE (symbolP, T_NULL);
00322   S_SET_STORAGE_CLASS (symbolP, 0);
00323   S_SET_NUMBER_AUXILIARY (symbolP, 0);
00324 
00325   if (S_IS_STRING (symbolP))
00326     SF_SET_STRING (symbolP);
00327 
00328   if (S_IS_LOCAL (symbolP))
00329     SF_SET_LOCAL (symbolP);
00330 }
00331 
00332 void
00333 coff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP)
00334 {
00335   long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
00336   combined_entry_type * s = xmalloc (sz);
00337 
00338   memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native, sz);
00339   coffsymbol (symbol_get_bfdsym (newsymP))->native = s;
00340 
00341   SF_SET (newsymP, SF_GET (orgsymP));
00342 }
00343 
00344 
00345 /* Handle .ln directives.  */
00346 
00347 static symbolS *current_lineno_sym;
00348 static struct line_no *line_nos;
00349 /* FIXME:  Blindly assume all .ln directives will be in the .text section.  */
00350 int coff_n_line_nos;
00351 
00352 static void
00353 add_lineno (fragS * frag, addressT offset, int num)
00354 {
00355   struct line_no * new_line = xmalloc (sizeof (* new_line));
00356 
00357   if (!current_lineno_sym)
00358     abort ();
00359 
00360 #ifndef OBJ_XCOFF
00361   /* The native aix assembler accepts negative line number.  */
00362 
00363   if (num <= 0)
00364     {
00365       /* Zero is used as an end marker in the file.  */
00366       as_warn (_("Line numbers must be positive integers\n"));
00367       num = 1;
00368     }
00369 #endif /* OBJ_XCOFF */
00370   new_line->next = line_nos;
00371   new_line->frag = frag;
00372   new_line->l.line_number = num;
00373   new_line->l.u.offset = offset;
00374   line_nos = new_line;
00375   coff_n_line_nos++;
00376 }
00377 
00378 void
00379 coff_add_linesym (symbolS *sym)
00380 {
00381   if (line_nos)
00382     {
00383       coffsymbol (symbol_get_bfdsym (current_lineno_sym))->lineno =
00384        (alent *) line_nos;
00385       coff_n_line_nos++;
00386       line_nos = 0;
00387     }
00388   current_lineno_sym = sym;
00389 }
00390 
00391 static void
00392 obj_coff_ln (int appline)
00393 {
00394   int l;
00395 
00396   if (! appline && def_symbol_in_progress != NULL)
00397     {
00398       as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
00399       demand_empty_rest_of_line ();
00400       return;
00401     }
00402 
00403   l = get_absolute_expression ();
00404 
00405   /* If there is no lineno symbol, treat a .ln
00406      directive as if it were a .appline directive.  */
00407   if (appline || current_lineno_sym == NULL)
00408     new_logical_line ((char *) NULL, l - 1);
00409   else
00410     add_lineno (frag_now, frag_now_fix (), l);
00411 
00412 #ifndef NO_LISTING
00413   {
00414     extern int listing;
00415 
00416     if (listing)
00417       {
00418        if (! appline)
00419          l += coff_line_base - 1;
00420        listing_source_line (l);
00421       }
00422   }
00423 #endif
00424 
00425   demand_empty_rest_of_line ();
00426 }
00427 
00428 /* .loc is essentially the same as .ln; parse it for assembler
00429    compatibility.  */
00430 
00431 static void
00432 obj_coff_loc (int ignore ATTRIBUTE_UNUSED)
00433 {
00434   int lineno;
00435 
00436   /* FIXME: Why do we need this check?  We need it for ECOFF, but why
00437      do we need it for COFF?  */
00438   if (now_seg != text_section)
00439     {
00440       as_warn (_(".loc outside of .text"));
00441       demand_empty_rest_of_line ();
00442       return;
00443     }
00444 
00445   if (def_symbol_in_progress != NULL)
00446     {
00447       as_warn (_(".loc pseudo-op inside .def/.endef: ignored."));
00448       demand_empty_rest_of_line ();
00449       return;
00450     }
00451 
00452   /* Skip the file number.  */
00453   SKIP_WHITESPACE ();
00454   get_absolute_expression ();
00455   SKIP_WHITESPACE ();
00456 
00457   lineno = get_absolute_expression ();
00458 
00459 #ifndef NO_LISTING
00460   {
00461     extern int listing;
00462 
00463     if (listing)
00464       {
00465        lineno += coff_line_base - 1;
00466        listing_source_line (lineno);
00467       }
00468   }
00469 #endif
00470 
00471   demand_empty_rest_of_line ();
00472 
00473   add_lineno (frag_now, frag_now_fix (), lineno);
00474 }
00475 
00476 /* Handle the .ident pseudo-op.  */
00477 
00478 static void
00479 obj_coff_ident (int ignore ATTRIBUTE_UNUSED)
00480 {
00481   segT current_seg = now_seg;
00482   subsegT current_subseg = now_subseg;
00483 
00484 #ifdef TE_PE
00485   {
00486     segT sec;
00487 
00488     /* We could put it in .comment, but that creates an extra section
00489        that shouldn't be loaded into memory, which requires linker
00490        changes...  For now, until proven otherwise, use .rdata.  */
00491     sec = subseg_new (".rdata$zzz", 0);
00492     bfd_set_section_flags (stdoutput, sec,
00493                         ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
00494                          & bfd_applicable_section_flags (stdoutput)));
00495   }
00496 #else
00497   subseg_new (".comment", 0);
00498 #endif
00499 
00500   stringer (1);
00501   subseg_set (current_seg, current_subseg);
00502 }
00503 
00504 /* Handle .def directives.
00505 
00506    One might ask : why can't we symbol_new if the symbol does not
00507    already exist and fill it with debug information.  Because of
00508    the C_EFCN special symbol. It would clobber the value of the
00509    function symbol before we have a chance to notice that it is
00510    a C_EFCN. And a second reason is that the code is more clear this
00511    way. (at least I think it is :-).  */
00512 
00513 #define SKIP_SEMI_COLON()   while (*input_line_pointer++ != ';')
00514 #define SKIP_WHITESPACES()  while (*input_line_pointer == ' ' || \
00515                                    *input_line_pointer == '\t')  \
00516                                   input_line_pointer++;
00517 
00518 static void
00519 obj_coff_def (int what ATTRIBUTE_UNUSED)
00520 {
00521   char name_end;            /* Char after the end of name.  */
00522   char *symbol_name;        /* Name of the debug symbol.  */
00523   char *symbol_name_copy;   /* Temporary copy of the name.  */
00524   unsigned int symbol_name_length;
00525 
00526   if (def_symbol_in_progress != NULL)
00527     {
00528       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
00529       demand_empty_rest_of_line ();
00530       return;
00531     }
00532 
00533   SKIP_WHITESPACES ();
00534 
00535   symbol_name = input_line_pointer;
00536   name_end = get_symbol_end ();
00537   symbol_name_length = strlen (symbol_name);
00538   symbol_name_copy = xmalloc (symbol_name_length + 1);
00539   strcpy (symbol_name_copy, symbol_name);
00540 #ifdef tc_canonicalize_symbol_name
00541   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
00542 #endif
00543 
00544   /* Initialize the new symbol.  */
00545   def_symbol_in_progress = symbol_make (symbol_name_copy);
00546   symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
00547   S_SET_VALUE (def_symbol_in_progress, 0);
00548 
00549   if (S_IS_STRING (def_symbol_in_progress))
00550     SF_SET_STRING (def_symbol_in_progress);
00551 
00552   *input_line_pointer = name_end;
00553 
00554   demand_empty_rest_of_line ();
00555 }
00556 
00557 unsigned int dim_index;
00558 
00559 static void
00560 obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
00561 {
00562   symbolS *symbolP = NULL;
00563 
00564   dim_index = 0;
00565   if (def_symbol_in_progress == NULL)
00566     {
00567       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
00568       demand_empty_rest_of_line ();
00569       return;
00570     }
00571 
00572   /* Set the section number according to storage class.  */
00573   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
00574     {
00575     case C_STRTAG:
00576     case C_ENTAG:
00577     case C_UNTAG:
00578       SF_SET_TAG (def_symbol_in_progress);
00579       /* Fall through.  */
00580     case C_FILE:
00581     case C_TPDEF:
00582       SF_SET_DEBUG (def_symbol_in_progress);
00583       S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
00584       break;
00585 
00586     case C_EFCN:
00587       SF_SET_LOCAL (def_symbol_in_progress);     /* Do not emit this symbol.  */
00588       /* Fall through.  */
00589     case C_BLOCK:
00590       SF_SET_PROCESS (def_symbol_in_progress);   /* Will need processing before writing.  */
00591       /* Fall through.  */
00592     case C_FCN:
00593       {
00594        const char *name;
00595 
00596        S_SET_SEGMENT (def_symbol_in_progress, text_section);
00597 
00598        name = S_GET_NAME (def_symbol_in_progress);
00599        if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
00600          {
00601            switch (name[1])
00602              {
00603              case 'b':
00604               /* .bf */
00605               if (! in_function ())
00606                 as_warn (_("`%s' symbol without preceding function"), name);
00607               /* Will need relocating.  */
00608               SF_SET_PROCESS (def_symbol_in_progress);
00609               clear_function ();
00610               break;
00611 #ifdef TE_PE
00612              case 'e':
00613               /* .ef */
00614               /* The MS compilers output the actual endline, not the
00615                  function-relative one... we want to match without
00616                  changing the assembler input.  */
00617               SA_SET_SYM_LNNO (def_symbol_in_progress,
00618                              (SA_GET_SYM_LNNO (def_symbol_in_progress)
00619                               + coff_line_base));
00620               break;
00621 #endif
00622              }
00623          }
00624       }
00625       break;
00626 
00627 #ifdef C_AUTOARG
00628     case C_AUTOARG:
00629 #endif /* C_AUTOARG */
00630     case C_AUTO:
00631     case C_REG:
00632     case C_ARG:
00633     case C_REGPARM:
00634     case C_FIELD:
00635 
00636     /* According to the COFF documentation:
00637 
00638        http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html
00639 
00640        A special section number (-2) marks symbolic debugging symbols,
00641        including structure/union/enumeration tag names, typedefs, and
00642        the name of the file. A section number of -1 indicates that the
00643        symbol has a value but is not relocatable. Examples of
00644        absolute-valued symbols include automatic and register variables,
00645        function arguments, and .eos symbols.
00646 
00647        But from Ian Lance Taylor:
00648 
00649        http://sources.redhat.com/ml/binutils/2000-08/msg00202.html
00650 
00651        the actual tools all marked them as section -1. So the GNU COFF
00652        assembler follows historical COFF assemblers.
00653 
00654        However, it causes problems for djgpp
00655 
00656        http://sources.redhat.com/ml/binutils/2000-08/msg00210.html
00657 
00658        By defining STRICTCOFF, a COFF port can make the assembler to
00659        follow the documented behavior.  */
00660 #ifdef STRICTCOFF
00661     case C_MOS:
00662     case C_MOE:
00663     case C_MOU:
00664     case C_EOS:
00665 #endif
00666       SF_SET_DEBUG (def_symbol_in_progress);
00667       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
00668       break;
00669 
00670 #ifndef STRICTCOFF
00671     case C_MOS:
00672     case C_MOE:
00673     case C_MOU:
00674     case C_EOS:
00675       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
00676       break;
00677 #endif
00678 
00679     case C_EXT:
00680     case C_WEAKEXT:
00681 #ifdef TE_PE
00682     case C_NT_WEAK:
00683 #endif
00684     case C_STAT:
00685     case C_LABEL:
00686       /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
00687       break;
00688 
00689     default:
00690     case C_USTATIC:
00691     case C_EXTDEF:
00692     case C_ULABEL:
00693       as_warn (_("unexpected storage class %d"),
00694               S_GET_STORAGE_CLASS (def_symbol_in_progress));
00695       break;
00696     }
00697 
00698   /* Now that we have built a debug symbol, try to find if we should
00699      merge with an existing symbol or not.  If a symbol is C_EFCN or
00700      absolute_section or untagged SEG_DEBUG it never merges.  We also
00701      don't merge labels, which are in a different namespace, nor
00702      symbols which have not yet been defined since they are typically
00703      unique, nor do we merge tags with non-tags.  */
00704 
00705   /* Two cases for functions.  Either debug followed by definition or
00706      definition followed by debug.  For definition first, we will
00707      merge the debug symbol into the definition.  For debug first, the
00708      lineno entry MUST point to the definition function or else it
00709      will point off into space when obj_crawl_symbol_chain() merges
00710      the debug symbol into the real symbol.  Therefor, let's presume
00711      the debug symbol is a real function reference.  */
00712 
00713   /* FIXME-SOON If for some reason the definition label/symbol is
00714      never seen, this will probably leave an undefined symbol at link
00715      time.  */
00716 
00717   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
00718       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
00719       || (streq (bfd_get_section_name (stdoutput,
00720                                    S_GET_SEGMENT (def_symbol_in_progress)),
00721                "*DEBUG*")
00722          && !SF_GET_TAG (def_symbol_in_progress))
00723       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
00724       || ! symbol_constant_p (def_symbol_in_progress)
00725       || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL
00726       || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
00727     {
00728       /* If it already is at the end of the symbol list, do nothing */
00729       if (def_symbol_in_progress != symbol_lastP)
00730        {
00731          symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
00732          symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
00733                       &symbol_lastP);
00734        }
00735     }
00736   else
00737     {
00738       /* This symbol already exists, merge the newly created symbol
00739         into the old one.  This is not mandatory. The linker can
00740         handle duplicate symbols correctly. But I guess that it save
00741         a *lot* of space if the assembly file defines a lot of
00742         symbols. [loic]  */
00743 
00744       /* The debug entry (def_symbol_in_progress) is merged into the
00745         previous definition.  */
00746 
00747       c_symbol_merge (def_symbol_in_progress, symbolP);
00748       symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
00749 
00750       def_symbol_in_progress = symbolP;
00751 
00752       if (SF_GET_FUNCTION (def_symbol_in_progress)
00753          || SF_GET_TAG (def_symbol_in_progress)
00754          || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
00755        {
00756          /* For functions, and tags, and static symbols, the symbol
00757             *must* be where the debug symbol appears.  Move the
00758             existing symbol to the current place.  */
00759          /* If it already is at the end of the symbol list, do nothing.  */
00760          if (def_symbol_in_progress != symbol_lastP)
00761            {
00762              symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
00763              symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
00764            }
00765        }
00766     }
00767 
00768   if (SF_GET_TAG (def_symbol_in_progress))
00769     {
00770       symbolS *oldtag;
00771 
00772       oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress));
00773       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
00774        tag_insert (S_GET_NAME (def_symbol_in_progress),
00775                   def_symbol_in_progress);
00776     }
00777 
00778   if (SF_GET_FUNCTION (def_symbol_in_progress))
00779     {
00780       know (sizeof (def_symbol_in_progress) <= sizeof (long));
00781       set_function (def_symbol_in_progress);
00782       SF_SET_PROCESS (def_symbol_in_progress);
00783 
00784       if (symbolP == NULL)
00785        /* That is, if this is the first time we've seen the
00786           function.  */
00787        symbol_table_insert (def_symbol_in_progress);
00788 
00789     }
00790 
00791   def_symbol_in_progress = NULL;
00792   demand_empty_rest_of_line ();
00793 }
00794 
00795 static void
00796 obj_coff_dim (int ignore ATTRIBUTE_UNUSED)
00797 {
00798   int dim_index;
00799 
00800   if (def_symbol_in_progress == NULL)
00801     {
00802       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
00803       demand_empty_rest_of_line ();
00804       return;
00805     }
00806 
00807   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
00808 
00809   for (dim_index = 0; dim_index < DIMNUM; dim_index++)
00810     {
00811       SKIP_WHITESPACES ();
00812       SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
00813                      get_absolute_expression ());
00814 
00815       switch (*input_line_pointer)
00816        {
00817        case ',':
00818          input_line_pointer++;
00819          break;
00820 
00821        default:
00822          as_warn (_("badly formed .dim directive ignored"));
00823          /* Fall through.  */
00824        case '\n':
00825        case ';':
00826          dim_index = DIMNUM;
00827          break;
00828        }
00829     }
00830 
00831   demand_empty_rest_of_line ();
00832 }
00833 
00834 static void
00835 obj_coff_line (int ignore ATTRIBUTE_UNUSED)
00836 {
00837   int this_base;
00838 
00839   if (def_symbol_in_progress == NULL)
00840     {
00841       /* Probably stabs-style line?  */
00842       obj_coff_ln (0);
00843       return;
00844     }
00845 
00846   this_base = get_absolute_expression ();
00847   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
00848     coff_line_base = this_base;
00849 
00850   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
00851   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
00852 
00853   demand_empty_rest_of_line ();
00854 
00855 #ifndef NO_LISTING
00856   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
00857     {
00858       extern int listing;
00859 
00860       if (listing)
00861        listing_source_line ((unsigned int) this_base);
00862     }
00863 #endif
00864 }
00865 
00866 static void
00867 obj_coff_size (int ignore ATTRIBUTE_UNUSED)
00868 {
00869   if (def_symbol_in_progress == NULL)
00870     {
00871       as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
00872       demand_empty_rest_of_line ();
00873       return;
00874     }
00875 
00876   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
00877   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
00878   demand_empty_rest_of_line ();
00879 }
00880 
00881 static void
00882 obj_coff_scl (int ignore ATTRIBUTE_UNUSED)
00883 {
00884   if (def_symbol_in_progress == NULL)
00885     {
00886       as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
00887       demand_empty_rest_of_line ();
00888       return;
00889     }
00890 
00891   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
00892   demand_empty_rest_of_line ();
00893 }
00894 
00895 static void
00896 obj_coff_tag (int ignore ATTRIBUTE_UNUSED)
00897 {
00898   char *symbol_name;
00899   char name_end;
00900 
00901   if (def_symbol_in_progress == NULL)
00902     {
00903       as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
00904       demand_empty_rest_of_line ();
00905       return;
00906     }
00907 
00908   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
00909   symbol_name = input_line_pointer;
00910   name_end = get_symbol_end ();
00911 
00912 #ifdef tc_canonicalize_symbol_name
00913   symbol_name = tc_canonicalize_symbol_name (symbol_name);
00914 #endif
00915 
00916   /* Assume that the symbol referred to by .tag is always defined.
00917      This was a bad assumption.  I've added find_or_make. xoxorich.  */
00918   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
00919                    tag_find_or_make (symbol_name));
00920   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
00921     as_warn (_("tag not found for .tag %s"), symbol_name);
00922 
00923   SF_SET_TAGGED (def_symbol_in_progress);
00924   *input_line_pointer = name_end;
00925 
00926   demand_empty_rest_of_line ();
00927 }
00928 
00929 static void
00930 obj_coff_type (int ignore ATTRIBUTE_UNUSED)
00931 {
00932   if (def_symbol_in_progress == NULL)
00933     {
00934       as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
00935       demand_empty_rest_of_line ();
00936       return;
00937     }
00938 
00939   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
00940 
00941   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
00942       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
00943     SF_SET_FUNCTION (def_symbol_in_progress);
00944 
00945   demand_empty_rest_of_line ();
00946 }
00947 
00948 static void
00949 obj_coff_val (int ignore ATTRIBUTE_UNUSED)
00950 {
00951   if (def_symbol_in_progress == NULL)
00952     {
00953       as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
00954       demand_empty_rest_of_line ();
00955       return;
00956     }
00957 
00958   if (is_name_beginner (*input_line_pointer))
00959     {
00960       char *symbol_name = input_line_pointer;
00961       char name_end = get_symbol_end ();
00962 
00963 #ifdef tc_canonicalize_symbol_name
00964   symbol_name = tc_canonicalize_symbol_name (symbol_name);
00965 #endif
00966       if (streq (symbol_name, "."))
00967        {
00968          /* If the .val is != from the .def (e.g. statics).  */
00969          symbol_set_frag (def_symbol_in_progress, frag_now);
00970          S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
00971        }
00972       else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name))
00973        {
00974          expressionS exp;
00975 
00976          exp.X_op = O_symbol;
00977          exp.X_add_symbol = symbol_find_or_make (symbol_name);
00978          exp.X_op_symbol = NULL;
00979          exp.X_add_number = 0;
00980          symbol_set_value_expression (def_symbol_in_progress, &exp);
00981 
00982          /* If the segment is undefined when the forward reference is
00983             resolved, then copy the segment id from the forward
00984             symbol.  */
00985          SF_SET_GET_SEGMENT (def_symbol_in_progress);
00986 
00987          /* FIXME: gcc can generate address expressions here in
00988             unusual cases (search for "obscure" in sdbout.c).  We
00989             just ignore the offset here, thus generating incorrect
00990             debugging information.  We ignore the rest of the line
00991             just below.  */
00992        }
00993       /* Otherwise, it is the name of a non debug symbol and its value
00994          will be calculated later.  */
00995       *input_line_pointer = name_end;
00996     }
00997   else
00998     {
00999       S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
01000     }
01001 
01002   demand_empty_rest_of_line ();
01003 }
01004 
01005 #ifdef TE_PE
01006 
01007 /* Return nonzero if name begins with weak alternate symbol prefix.  */
01008 
01009 static int
01010 weak_is_altname (const char * name)
01011 {
01012   return strneq (name, weak_altprefix, sizeof (weak_altprefix) - 1);
01013 }
01014 
01015 /* Return the name of the alternate symbol
01016    name corresponding to a weak symbol's name.  */
01017 
01018 static const char *
01019 weak_name2altname (const char * name)
01020 {
01021   char *alt_name;
01022 
01023   alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name));
01024   strcpy (alt_name, weak_altprefix);
01025   return strcat (alt_name, name);
01026 }
01027 
01028 /* Return the name of the weak symbol corresponding to an
01029    alternate symbol.  */
01030 
01031 static const char *
01032 weak_altname2name (const char * name)
01033 {
01034   char * weak_name;
01035   char * dot;
01036 
01037   assert (weak_is_altname (name));
01038 
01039   weak_name = xstrdup (name + 6);
01040   if ((dot = strchr (weak_name, '.')))
01041     *dot = 0;
01042   return weak_name;
01043 }
01044 
01045 /* Make a weak symbol name unique by
01046    appending the name of an external symbol.  */
01047 
01048 static const char *
01049 weak_uniquify (const char * name)
01050 {
01051   char *ret;
01052   const char * unique = "";
01053 
01054 #ifdef USE_UNIQUE
01055   if (an_external_name != NULL)
01056     unique = an_external_name;
01057 #endif
01058   assert (weak_is_altname (name));
01059 
01060   if (strchr (name + sizeof (weak_altprefix), '.'))
01061     return name;
01062 
01063   ret = xmalloc (strlen (name) + strlen (unique) + 2);
01064   strcpy (ret, name);
01065   strcat (ret, ".");
01066   strcat (ret, unique);
01067   return ret;
01068 }
01069 
01070 void
01071 pecoff_obj_set_weak_hook (symbolS *symbolP)
01072 {
01073   symbolS *alternateP;
01074 
01075   /* See _Microsoft Portable Executable and Common Object
01076      File Format Specification_, section 5.5.3.
01077      Create a symbol representing the alternate value.
01078      coff_frob_symbol will set the value of this symbol from
01079      the value of the weak symbol itself.  */
01080   S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
01081   S_SET_NUMBER_AUXILIARY (symbolP, 1);
01082   SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
01083 
01084   alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
01085   S_SET_EXTERNAL (alternateP);
01086   S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
01087 
01088   SA_SET_SYM_TAGNDX (symbolP, alternateP);
01089 }
01090 
01091 void
01092 pecoff_obj_clear_weak_hook (symbolS *symbolP)
01093 {
01094   symbolS *alternateP;
01095 
01096   S_SET_STORAGE_CLASS (symbolP, 0);
01097   SA_SET_SYM_FSIZE (symbolP, 0);
01098 
01099   alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
01100   S_CLEAR_EXTERNAL (alternateP);
01101 }
01102 
01103 #endif  /* TE_PE */
01104 
01105 /* Handle .weak.  This is a GNU extension in formats other than PE. */
01106 
01107 static void
01108 obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
01109 {
01110   char *name;
01111   int c;
01112   symbolS *symbolP;
01113 
01114   do
01115     {
01116       name = input_line_pointer;
01117       c = get_symbol_end ();
01118       if (*name == 0)
01119        {
01120          as_warn (_("badly formed .weak directive ignored"));
01121          ignore_rest_of_line ();
01122          return;
01123        }
01124       c = 0;
01125       symbolP = symbol_find_or_make (name);
01126       *input_line_pointer = c;
01127       SKIP_WHITESPACE ();
01128       S_SET_WEAK (symbolP);
01129 
01130       if (c == ',')
01131        {
01132          input_line_pointer++;
01133          SKIP_WHITESPACE ();
01134          if (*input_line_pointer == '\n')
01135            c = '\n';
01136        }
01137 
01138     }
01139   while (c == ',');
01140 
01141   demand_empty_rest_of_line ();
01142 }
01143 
01144 void
01145 coff_obj_read_begin_hook (void)
01146 {
01147   /* These had better be the same.  Usually 18 bytes.  */
01148   know (sizeof (SYMENT) == sizeof (AUXENT));
01149   know (SYMESZ == AUXESZ);
01150   tag_init ();
01151 }
01152 
01153 symbolS *coff_last_function;
01154 #ifndef OBJ_XCOFF
01155 static symbolS *coff_last_bf;
01156 #endif
01157 
01158 void
01159 coff_frob_symbol (symbolS *symp, int *punt)
01160 {
01161   static symbolS *last_tagP;
01162   static stack *block_stack;
01163   static symbolS *set_end;
01164   symbolS *next_set_end = NULL;
01165 
01166   if (symp == &abs_symbol)
01167     {
01168       *punt = 1;
01169       return;
01170     }
01171 
01172   if (current_lineno_sym)
01173     coff_add_linesym (NULL);
01174 
01175   if (!block_stack)
01176     block_stack = stack_init (512, sizeof (symbolS*));
01177 
01178 #ifdef TE_PE
01179   if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
01180       && ! S_IS_WEAK (symp)
01181       && weak_is_altname (S_GET_NAME (symp)))
01182     {
01183       /* This is a weak alternate symbol.  All processing of
01184         PECOFFweak symbols is done here, through the alternate.  */
01185       symbolS *weakp = symbol_find_noref (weak_altname2name
01186                                      (S_GET_NAME (symp)), 1);
01187 
01188       assert (weakp);
01189       assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
01190 
01191       if (! S_IS_WEAK (weakp))
01192        {
01193          /* The symbol was turned from weak to strong.  Discard altname.  */
01194          *punt = 1;
01195          return;
01196        }
01197       else if (symbol_equated_p (weakp))
01198        {
01199          /* The weak symbol has an alternate specified; symp is unneeded.  */
01200          S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
01201          SA_SET_SYM_TAGNDX (weakp,
01202            symbol_get_value_expression (weakp)->X_add_symbol);
01203 
01204          S_CLEAR_EXTERNAL (symp);
01205          *punt = 1;
01206          return;
01207        }
01208       else
01209        {
01210          /* The weak symbol has been assigned an alternate value.
01211              Copy this value to symp, and set symp as weakp's alternate.  */
01212          if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
01213            {
01214              S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
01215              S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
01216            }
01217 
01218          if (S_IS_DEFINED (weakp))
01219            {
01220              /* This is a defined weak symbol.  Copy value information
01221                 from the weak symbol itself to the alternate symbol.  */
01222              symbol_set_value_expression (symp,
01223                                       symbol_get_value_expression (weakp));
01224              symbol_set_frag (symp, symbol_get_frag (weakp));
01225              S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
01226            }
01227          else
01228            {
01229              /* This is an undefined weak symbol.
01230                Define the alternate symbol to zero.  */
01231              S_SET_VALUE (symp, 0);
01232              S_SET_SEGMENT (symp, absolute_section);
01233            }
01234 
01235          S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
01236          S_SET_STORAGE_CLASS (symp, C_EXT);
01237 
01238          S_SET_VALUE (weakp, 0);
01239          S_SET_SEGMENT (weakp, undefined_section);
01240        }
01241     }
01242 #else /* TE_PE */
01243   if (S_IS_WEAK (symp))
01244     S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
01245 #endif /* TE_PE */
01246 
01247   if (!S_IS_DEFINED (symp)
01248       && !S_IS_WEAK (symp)
01249       && S_GET_STORAGE_CLASS (symp) != C_STAT)
01250     S_SET_STORAGE_CLASS (symp, C_EXT);
01251 
01252   if (!SF_GET_DEBUG (symp))
01253     {
01254       symbolS * real;
01255 
01256       if (!SF_GET_LOCAL (symp)
01257          && !SF_GET_STATICS (symp)
01258          && S_GET_STORAGE_CLASS (symp) != C_LABEL
01259          && symbol_constant_p (symp)
01260          && (real = symbol_find_noref (S_GET_NAME (symp), 1))
01261          && S_GET_STORAGE_CLASS (real) == C_NULL
01262          && real != symp)
01263        {
01264          c_symbol_merge (symp, real);
01265          *punt = 1;
01266          return;
01267        }
01268 
01269       if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
01270        {
01271          assert (S_GET_VALUE (symp) == 0);
01272          if (S_IS_WEAKREFD (symp))
01273            *punt = 1;
01274          else
01275            S_SET_EXTERNAL (symp);
01276        }
01277       else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
01278        {
01279          if (S_GET_SEGMENT (symp) == text_section
01280              && symp != seg_info (text_section)->sym)
01281            S_SET_STORAGE_CLASS (symp, C_LABEL);
01282          else
01283            S_SET_STORAGE_CLASS (symp, C_STAT);
01284        }
01285 
01286       if (SF_GET_PROCESS (symp))
01287        {
01288          if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
01289            {
01290              if (streq (S_GET_NAME (symp), ".bb"))
01291               stack_push (block_stack, (char *) &symp);
01292              else
01293               {
01294                 symbolS *begin;
01295 
01296                 begin = *(symbolS **) stack_pop (block_stack);
01297                 if (begin == 0)
01298                   as_warn (_("mismatched .eb"));
01299                 else
01300                   next_set_end = begin;
01301               }
01302            }
01303 
01304          if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
01305            {
01306              union internal_auxent *auxp;
01307 
01308              coff_last_function = symp;
01309              if (S_GET_NUMBER_AUXILIARY (symp) < 1)
01310               S_SET_NUMBER_AUXILIARY (symp, 1);
01311              auxp = SYM_AUXENT (symp);
01312              memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
01313                     sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
01314            }
01315 
01316          if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
01317            {
01318              if (coff_last_function == 0)
01319               as_fatal (_("C_EFCN symbol for %s out of scope"),
01320                        S_GET_NAME (symp));
01321              SA_SET_SYM_FSIZE (coff_last_function,
01322                             (long) (S_GET_VALUE (symp)
01323                                    - S_GET_VALUE (coff_last_function)));
01324              next_set_end = coff_last_function;
01325              coff_last_function = 0;
01326            }
01327        }
01328 
01329       if (S_IS_EXTERNAL (symp))
01330        S_SET_STORAGE_CLASS (symp, C_EXT);
01331       else if (SF_GET_LOCAL (symp))
01332        *punt = 1;
01333 
01334       if (SF_GET_FUNCTION (symp))
01335        symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
01336     }
01337 
01338   /* Double check weak symbols.  */
01339   if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
01340     as_bad (_("Symbol `%s' can not be both weak and common"),
01341            S_GET_NAME (symp));
01342 
01343   if (SF_GET_TAG (symp))
01344     last_tagP = symp;
01345   else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
01346     next_set_end = last_tagP;
01347 
01348 #ifdef OBJ_XCOFF
01349   /* This is pretty horrible, but we have to set *punt correctly in
01350      order to call SA_SET_SYM_ENDNDX correctly.  */
01351   if (! symbol_used_in_reloc_p (symp)
01352       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
01353          || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
01354              && ! symbol_get_tc (symp)->output
01355              && S_GET_STORAGE_CLASS (symp) != C_FILE)))
01356     *punt = 1;
01357 #endif
01358 
01359   if (set_end != (symbolS *) NULL
01360       && ! *punt
01361       && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
01362          || (S_IS_DEFINED (symp)
01363              && ! S_IS_COMMON (symp)
01364              && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
01365     {
01366       SA_SET_SYM_ENDNDX (set_end, symp);
01367       set_end = NULL;
01368     }
01369 
01370   if (next_set_end != NULL)
01371     {
01372       if (set_end != NULL)
01373        as_warn ("Warning: internal error: forgetting to set endndx of %s",
01374                S_GET_NAME (set_end));
01375       set_end = next_set_end;
01376     }
01377 
01378 #ifndef OBJ_XCOFF
01379   if (! *punt
01380       && S_GET_STORAGE_CLASS (symp) == C_FCN
01381       && streq (S_GET_NAME (symp), ".bf"))
01382     {
01383       if (coff_last_bf != NULL)
01384        SA_SET_SYM_ENDNDX (coff_last_bf, symp);
01385       coff_last_bf = symp;
01386     }
01387 #endif
01388   if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
01389     {
01390       int i;
01391       struct line_no *lptr;
01392       alent *l;
01393 
01394       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
01395       for (i = 0; lptr; lptr = lptr->next)
01396        i++;
01397       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
01398 
01399       /* We need i entries for line numbers, plus 1 for the first
01400         entry which BFD will override, plus 1 for the last zero
01401         entry (a marker for BFD).  */
01402       l = xmalloc ((i + 2) * sizeof (* l));
01403       coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
01404       l[i + 1].line_number = 0;
01405       l[i + 1].u.sym = NULL;
01406       for (; i > 0; i--)
01407        {
01408          if (lptr->frag)
01409            lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
01410          l[i] = lptr->l;
01411          lptr = lptr->next;
01412        }
01413     }
01414 }
01415 
01416 void
01417 coff_adjust_section_syms (bfd *abfd ATTRIBUTE_UNUSED,
01418                        asection *sec,
01419                        void * x ATTRIBUTE_UNUSED)
01420 {
01421   symbolS *secsym;
01422   segment_info_type *seginfo = seg_info (sec);
01423   int nlnno, nrelocs = 0;
01424 
01425   /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
01426      tc-ppc.c.  Do not get confused by it.  */
01427   if (seginfo == NULL)
01428     return;
01429 
01430   if (streq (sec->name, ".text"))
01431     nlnno = coff_n_line_nos;
01432   else
01433     nlnno = 0;
01434   {
01435     /* @@ Hope that none of the fixups expand to more than one reloc
01436        entry...  */
01437     fixS *fixp = seginfo->fix_root;
01438     while (fixp)
01439       {
01440        if (! fixp->fx_done)
01441          nrelocs++;
01442        fixp = fixp->fx_next;
01443       }
01444   }
01445   if (bfd_get_section_size (sec) == 0
01446       && nrelocs == 0
01447       && nlnno == 0
01448       && sec != text_section
01449       && sec != data_section
01450       && sec != bss_section)
01451     return;
01452 
01453   secsym = section_symbol (sec);
01454   /* This is an estimate; we'll plug in the real value using
01455      SET_SECTION_RELOCS later */
01456   SA_SET_SCN_NRELOC (secsym, nrelocs);
01457   SA_SET_SCN_NLINNO (secsym, nlnno);
01458 }
01459 
01460 void
01461 coff_frob_file_after_relocs (void)
01462 {
01463   bfd_map_over_sections (stdoutput, coff_adjust_section_syms, NULL);
01464 }
01465 
01466 /* Implement the .section pseudo op:
01467        .section name {, "flags"}
01468                   ^         ^
01469                   |         +--- optional flags: 'b' for bss
01470                   |                              'i' for info
01471                   +-- section name               'l' for lib
01472                                                  'n' for noload
01473                                                  'o' for over
01474                                                  'w' for data
01475                                            'd' (apparently m88k for data)
01476                                                  'x' for text
01477                                            'r' for read-only data
01478                                            's' for shared data (PE)
01479    But if the argument is not a quoted string, treat it as a
01480    subsegment number.
01481 
01482    Note the 'a' flag is silently ignored.  This allows the same
01483    .section directive to be parsed in both ELF and COFF formats.  */
01484 
01485 void
01486 obj_coff_section (int ignore ATTRIBUTE_UNUSED)
01487 {
01488   /* Strip out the section name.  */
01489   char *section_name;
01490   char c;
01491   char *name;
01492   unsigned int exp;
01493   flagword flags, oldflags;
01494   asection *sec;
01495 
01496   if (flag_mri)
01497     {
01498       char type;
01499 
01500       s_mri_sect (&type);
01501       return;
01502     }
01503 
01504   section_name = input_line_pointer;
01505   c = get_symbol_end ();
01506 
01507   name = xmalloc (input_line_pointer - section_name + 1);
01508   strcpy (name, section_name);
01509 
01510   *input_line_pointer = c;
01511 
01512   SKIP_WHITESPACE ();
01513 
01514   exp = 0;
01515   flags = SEC_NO_FLAGS;
01516 
01517   if (*input_line_pointer == ',')
01518     {
01519       ++input_line_pointer;
01520       SKIP_WHITESPACE ();
01521       if (*input_line_pointer != '"')
01522        exp = get_absolute_expression ();
01523       else
01524        {
01525          unsigned char attr;
01526          int readonly_removed = 0;
01527          int load_removed = 0;
01528 
01529          while (attr = *++input_line_pointer,
01530                attr != '"'
01531                && ! is_end_of_line[attr])
01532            {
01533              switch (attr)
01534               {
01535               case 'b':
01536                 /* Uninitialised data section.  */
01537                 flags |= SEC_ALLOC;
01538                 flags &=~ SEC_LOAD;
01539                 break;
01540 
01541               case 'n':
01542                 /* Section not loaded.  */
01543                 flags &=~ SEC_LOAD;
01544                 flags |= SEC_NEVER_LOAD;
01545                 load_removed = 1;
01546                 break;
01547 
01548               case 's':
01549                 /* Shared section.  */
01550                 flags |= SEC_COFF_SHARED;
01551                 /* Fall through.  */
01552               case 'd':
01553                 /* Data section.  */
01554                 flags |= SEC_DATA;
01555                 if (! load_removed)
01556                   flags |= SEC_LOAD;
01557                 flags &=~ SEC_READONLY;
01558                 break;
01559 
01560               case 'w':
01561                 /* Writable section.  */
01562                 flags &=~ SEC_READONLY;
01563                 readonly_removed = 1;
01564                 break;
01565 
01566               case 'a':
01567                 /* Ignore.  Here for compatibility with ELF.  */
01568                 break;
01569 
01570               case 'r': /* Read-only section.  Implies a data section.  */
01571                 readonly_removed = 0;
01572                 /* Fall through.  */
01573               case 'x': /* Executable section.  */
01574                 /* If we are setting the 'x' attribute or if the 'r'
01575                    attribute is being used to restore the readonly status
01576                    of a code section (eg "wxr") then set the SEC_CODE flag,
01577                    otherwise set the SEC_DATA flag.  */
01578                 flags |= (attr == 'x' || (flags & SEC_CODE) ? SEC_CODE : SEC_DATA);
01579                 if (! load_removed)
01580                   flags |= SEC_LOAD;
01581                 /* Note - the READONLY flag is set here, even for the 'x'
01582                    attribute in order to be compatible with the MSVC
01583                    linker.  */
01584                 if (! readonly_removed)
01585                   flags |= SEC_READONLY;
01586                 break;
01587 
01588               case 'i': /* STYP_INFO */
01589               case 'l': /* STYP_LIB */
01590               case 'o': /* STYP_OVER */
01591                 as_warn (_("unsupported section attribute '%c'"), attr);
01592                 break;
01593 
01594               default:
01595                 as_warn (_("unknown section attribute '%c'"), attr);
01596                 break;
01597               }
01598            }
01599          if (attr == '"')
01600            ++input_line_pointer;
01601        }
01602     }
01603 
01604   sec = subseg_new (name, (subsegT) exp);
01605 
01606   oldflags = bfd_get_section_flags (stdoutput, sec);
01607   if (oldflags == SEC_NO_FLAGS)
01608     {
01609       /* Set section flags for a new section just created by subseg_new.
01610          Provide a default if no flags were parsed.  */
01611       if (flags == SEC_NO_FLAGS)
01612        flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;
01613 
01614 #ifdef COFF_LONG_SECTION_NAMES
01615       /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce
01616          sections so adjust_reloc_syms in write.c will correctly handle
01617          relocs which refer to non-local symbols in these sections.  */
01618       if (strneq (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1))
01619        flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
01620 #endif
01621 
01622       if (! bfd_set_section_flags (stdoutput, sec, flags))
01623        as_warn (_("error setting flags for \"%s\": %s"),
01624                bfd_section_name (stdoutput, sec),
01625                bfd_errmsg (bfd_get_error ()));
01626     }
01627   else if (flags != SEC_NO_FLAGS)
01628     {
01629       /* This section's attributes have already been set.  Warn if the
01630          attributes don't match.  */
01631       flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
01632                           | SEC_DATA | SEC_COFF_SHARED | SEC_NEVER_LOAD);
01633       if ((flags ^ oldflags) & matchflags)
01634        as_warn (_("Ignoring changed section attributes for %s"), name);
01635     }
01636 
01637   demand_empty_rest_of_line ();
01638 }
01639 
01640 void
01641 coff_adjust_symtab (void)
01642 {
01643   if (symbol_rootP == NULL
01644       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
01645     c_dot_file_symbol ("fake", 0);
01646 }
01647 
01648 void
01649 coff_frob_section (segT sec)
01650 {
01651   segT strsec;
01652   char *p;
01653   fragS *fragp;
01654   bfd_vma size, n_entries, mask;
01655   bfd_vma align_power = (bfd_vma)sec->alignment_power + OCTETS_PER_BYTE_POWER;
01656 
01657   /* The COFF back end in BFD requires that all section sizes be
01658      rounded up to multiples of the corresponding section alignments,
01659      supposedly because standard COFF has no other way of encoding alignment
01660      for sections.  If your COFF flavor has a different way of encoding
01661      section alignment, then skip this step, as TICOFF does.  */
01662   size = bfd_get_section_size (sec);
01663   mask = ((bfd_vma) 1 << align_power) - 1;
01664 #if !defined(TICOFF)
01665   if (size & mask)
01666     {
01667       bfd_vma new_size;
01668       fragS *last;
01669 
01670       new_size = (size + mask) & ~mask;
01671       bfd_set_section_size (stdoutput, sec, new_size);
01672 
01673       /* If the size had to be rounded up, add some padding in
01674          the last non-empty frag.  */
01675       fragp = seg_info (sec)->frchainP->frch_root;
01676       last = seg_info (sec)->frchainP->frch_last;
01677       while (fragp->fr_next != last)
01678        fragp = fragp->fr_next;
01679       last->fr_address = size;
01680       fragp->fr_offset += new_size - size;
01681     }
01682 #endif
01683 
01684   /* If the section size is non-zero, the section symbol needs an aux
01685      entry associated with it, indicating the size.  We don't know
01686      all the values yet; coff_frob_symbol will fill them in later.  */
01687 #ifndef TICOFF
01688   if (size != 0
01689       || sec == text_section
01690       || sec == data_section
01691       || sec == bss_section)
01692 #endif
01693     {
01694       symbolS *secsym = section_symbol (sec);
01695 
01696       S_SET_STORAGE_CLASS (secsym, C_STAT);
01697       S_SET_NUMBER_AUXILIARY (secsym, 1);
01698       SF_SET_STATICS (secsym);
01699       SA_SET_SCN_SCNLEN (secsym, size);
01700     }
01701 
01702   /* FIXME: These should be in a "stabs.h" file, or maybe as.h.  */
01703 #ifndef STAB_SECTION_NAME
01704 #define STAB_SECTION_NAME ".stab"
01705 #endif
01706 #ifndef STAB_STRING_SECTION_NAME
01707 #define STAB_STRING_SECTION_NAME ".stabstr"
01708 #endif
01709   if (! streq (STAB_STRING_SECTION_NAME, sec->name))
01710     return;
01711 
01712   strsec = sec;
01713   sec = subseg_get (STAB_SECTION_NAME, 0);
01714   /* size is already rounded up, since other section will be listed first */
01715   size = bfd_get_section_size (strsec);
01716 
01717   n_entries = bfd_get_section_size (sec) / 12 - 1;
01718 
01719   /* Find first non-empty frag.  It should be large enough.  */
01720   fragp = seg_info (sec)->frchainP->frch_root;
01721   while (fragp && fragp->fr_fix == 0)
01722     fragp = fragp->fr_next;
01723   assert (fragp != 0 && fragp->fr_fix >= 12);
01724 
01725   /* Store the values.  */
01726   p = fragp->fr_literal;
01727   bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
01728   bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
01729 }
01730 
01731 void
01732 obj_coff_init_stab_section (segT seg)
01733 {
01734   char *file;
01735   char *p;
01736   char *stabstr_name;
01737   unsigned int stroff;
01738 
01739   /* Make space for this first symbol.  */
01740   p = frag_more (12);
01741   /* Zero it out.  */
01742   memset (p, 0, 12);
01743   as_where (&file, (unsigned int *) NULL);
01744   stabstr_name = xmalloc (strlen (seg->name) + 4);
01745   strcpy (stabstr_name, seg->name);
01746   strcat (stabstr_name, "str");
01747   stroff = get_stab_string_offset (file, stabstr_name);
01748   know (stroff == 1);
01749   md_number_to_chars (p, stroff, 4);
01750 }
01751 
01752 #ifdef DEBUG
01753 const char *
01754 s_get_name (symbolS *s)
01755 {
01756   return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
01757 }
01758 
01759 void
01760 symbol_dump (void)
01761 {
01762   symbolS *symbolP;
01763 
01764   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
01765     printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
01766            (unsigned long) symbolP,
01767            S_GET_NAME (symbolP),
01768            (long) S_GET_DATA_TYPE (symbolP),
01769            S_GET_STORAGE_CLASS (symbolP),
01770            (int) S_GET_SEGMENT (symbolP));
01771 }
01772 
01773 #endif /* DEBUG */
01774 
01775 const pseudo_typeS coff_pseudo_table[] =
01776 {
01777   {"ABORT", s_abort, 0},
01778   {"appline", obj_coff_ln, 1},
01779   /* We accept the .bss directive for backward compatibility with
01780      earlier versions of gas.  */
01781   {"bss", obj_coff_bss, 0},
01782   {"def", obj_coff_def, 0},
01783   {"dim", obj_coff_dim, 0},
01784   {"endef", obj_coff_endef, 0},
01785   {"ident", obj_coff_ident, 0},
01786   {"line", obj_coff_line, 0},
01787   {"ln", obj_coff_ln, 0},
01788   {"scl", obj_coff_scl, 0},
01789   {"sect", obj_coff_section, 0},
01790   {"sect.s", obj_coff_section, 0},
01791   {"section", obj_coff_section, 0},
01792   {"section.s", obj_coff_section, 0},
01793   /* FIXME: We ignore the MRI short attribute.  */
01794   {"size", obj_coff_size, 0},
01795   {"tag", obj_coff_tag, 0},
01796   {"type", obj_coff_type, 0},
01797   {"val", obj_coff_val, 0},
01798   {"version", s_ignore, 0},
01799   {"loc", obj_coff_loc, 0},
01800   {"optim", s_ignore, 0},   /* For sun386i cc (?) */
01801   {"weak", obj_coff_weak, 0},
01802 #if defined TC_TIC4X
01803   /* The tic4x uses sdef instead of def.  */
01804   {"sdef", obj_coff_def, 0},
01805 #endif
01806   {NULL, NULL, 0}
01807 };
01808 
01809 
01810 /* Support for a COFF emulation.  */
01811 
01812 static void
01813 coff_pop_insert (void)
01814 {
01815   pop_insert (coff_pseudo_table);
01816 }
01817 
01818 static int
01819 coff_separate_stab_sections (void)
01820 {
01821   return 1;
01822 }
01823 
01824 const struct format_ops coff_format_ops =
01825 {
01826   bfd_target_coff_flavour,
01827   0,   /* dfl_leading_underscore */
01828   1,   /* emit_section_symbols */
01829   0,    /* begin */
01830   c_dot_file_symbol,
01831   coff_frob_symbol,
01832   0,   /* frob_file */
01833   0,   /* frob_file_before_adjust */
01834   0,   /* frob_file_before_fix */
01835   coff_frob_file_after_relocs,
01836   0,   /* s_get_size */
01837   0,   /* s_set_size */
01838   0,   /* s_get_align */
01839   0,   /* s_set_align */
01840   0,   /* s_get_other */
01841   0,   /* s_set_other */
01842   0,   /* s_get_desc */
01843   0,   /* s_set_desc */
01844   0,   /* s_get_type */
01845   0,   /* s_set_type */
01846   0,   /* copy_symbol_attributes */
01847   0,   /* generate_asm_lineno */
01848   0,   /* process_stab */
01849   coff_separate_stab_sections,
01850   obj_coff_init_stab_section,
01851   0,   /* sec_sym_ok_for_reloc */
01852   coff_pop_insert,
01853   0,   /* ecoff_set_ext */
01854   coff_obj_read_begin_hook,
01855   coff_obj_symbol_new_hook
01856 };