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