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