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