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