1 /* coff object file format
2    Copyright (C) 1989-2024 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);
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)319 c_dot_file_symbol (const char *filename)
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 ignore ATTRIBUTE_UNUSED)450 obj_coff_ln (int ignore ATTRIBUTE_UNUSED)
451 {
452   int l;
453 
454   if (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 directive
464      as if it were a (no longer existing) .appline one.  */
465   if (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           l += coff_line_base - 1;
477           listing_source_line (l);
478       }
479   }
480 #endif
481 
482   demand_empty_rest_of_line ();
483 }
484 
485 /* .loc is essentially the same as .ln; parse it for assembler
486    compatibility.  */
487 
488 static void
obj_coff_loc(int ignore ATTRIBUTE_UNUSED)489 obj_coff_loc (int ignore ATTRIBUTE_UNUSED)
490 {
491   int lineno;
492 
493   /* FIXME: Why do we need this check?  We need it for ECOFF, but why
494      do we need it for COFF?  */
495   if (now_seg != text_section)
496     {
497       as_warn (_(".loc outside of .text"));
498       demand_empty_rest_of_line ();
499       return;
500     }
501 
502   if (def_symbol_in_progress != NULL)
503     {
504       as_warn (_(".loc pseudo-op inside .def/.endef: ignored."));
505       demand_empty_rest_of_line ();
506       return;
507     }
508 
509   /* Skip the file number.  */
510   SKIP_WHITESPACE ();
511   get_absolute_expression ();
512   SKIP_WHITESPACE ();
513 
514   lineno = get_absolute_expression ();
515 
516 #ifndef NO_LISTING
517   {
518     extern int listing;
519 
520     if (listing)
521       {
522           lineno += coff_line_base - 1;
523           listing_source_line (lineno);
524       }
525   }
526 #endif
527 
528   demand_empty_rest_of_line ();
529 
530   add_lineno (frag_now, frag_now_fix (), lineno);
531 }
532 
533 /* Handle the .ident pseudo-op.  */
534 
535 static void
obj_coff_ident(int ignore ATTRIBUTE_UNUSED)536 obj_coff_ident (int ignore ATTRIBUTE_UNUSED)
537 {
538   segT current_seg = now_seg;
539   subsegT current_subseg = now_subseg;
540 
541 #ifdef TE_PE
542   {
543     segT sec;
544 
545     /* We could put it in .comment, but that creates an extra section
546        that shouldn't be loaded into memory, which requires linker
547        changes...  For now, until proven otherwise, use .rdata.  */
548     sec = subseg_new (".rdata$zzz", 0);
549     bfd_set_section_flags (sec,
550                                  ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
551                                   & bfd_applicable_section_flags (stdoutput)));
552   }
553 #else
554   subseg_new (".comment", 0);
555 #endif
556 
557   stringer (8 + 1);
558   subseg_set (current_seg, current_subseg);
559 }
560 
561 /* Handle .def directives.
562 
563    One might ask : why can't we symbol_new if the symbol does not
564    already exist and fill it with debug information.  Because of
565    the C_EFCN special symbol. It would clobber the value of the
566    function symbol before we have a chance to notice that it is
567    a C_EFCN. And a second reason is that the code is more clear this
568    way. (at least I think it is :-).  */
569 
570 #define SKIP_SEMI_COLON()     while (*input_line_pointer++ != ';')
571 #define SKIP_WHITESPACES()    while (*input_line_pointer == ' ' || \
572                                                *input_line_pointer == '\t')  \
573                                   input_line_pointer++;
574 
575 static void
obj_coff_def(int what ATTRIBUTE_UNUSED)576 obj_coff_def (int what ATTRIBUTE_UNUSED)
577 {
578   char name_end;              /* Char after the end of name.  */
579   char *symbol_name;                    /* Name of the debug symbol.  */
580   char *symbol_name_copy;     /* Temporary copy of the name.  */
581 
582   if (def_symbol_in_progress != NULL)
583     {
584       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
585       demand_empty_rest_of_line ();
586       return;
587     }
588 
589   SKIP_WHITESPACES ();
590 
591   name_end = get_symbol_name (&symbol_name);
592   symbol_name_copy = xstrdup (symbol_name);
593 #ifdef tc_canonicalize_symbol_name
594   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
595 #endif
596 
597   /* Initialize the new symbol.  */
598   def_symbol_in_progress = symbol_make (symbol_name_copy);
599   symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
600   S_SET_VALUE (def_symbol_in_progress, 0);
601 
602   if (S_IS_STRING (def_symbol_in_progress))
603     SF_SET_STRING (def_symbol_in_progress);
604 
605   (void) restore_line_pointer (name_end);
606 
607   demand_empty_rest_of_line ();
608 }
609 
610 static void
obj_coff_endef(int ignore ATTRIBUTE_UNUSED)611 obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
612 {
613   symbolS *symbolP = NULL;
614 
615   if (def_symbol_in_progress == NULL)
616     {
617       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
618       demand_empty_rest_of_line ();
619       return;
620     }
621 
622   /* Set the section number according to storage class.  */
623   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
624     {
625     case C_STRTAG:
626     case C_ENTAG:
627     case C_UNTAG:
628       SF_SET_TAG (def_symbol_in_progress);
629       /* Fall through.  */
630     case C_FILE:
631     case C_TPDEF:
632       SF_SET_DEBUG (def_symbol_in_progress);
633       S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
634       break;
635 
636     case C_EFCN:
637       SF_SET_LOCAL (def_symbol_in_progress);      /* Do not emit this symbol.  */
638       /* Fall through.  */
639     case C_BLOCK:
640       SF_SET_PROCESS (def_symbol_in_progress);    /* Will need processing before writing.  */
641       /* Fall through.  */
642     case C_FCN:
643       {
644           const char *name;
645 
646           S_SET_SEGMENT (def_symbol_in_progress, text_section);
647 
648           name = S_GET_NAME (def_symbol_in_progress);
649           if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
650             {
651               switch (name[1])
652                 {
653                 case 'b':
654                     /* .bf */
655                     if (! in_function ())
656                       as_warn (_("`%s' symbol without preceding function"), name);
657                     /* Will need relocating.  */
658                     SF_SET_PROCESS (def_symbol_in_progress);
659                     clear_function ();
660                     break;
661 #ifdef TE_PE
662                 case 'e':
663                     /* .ef */
664                     /* The MS compilers output the actual endline, not the
665                        function-relative one... we want to match without
666                        changing the assembler input.  */
667                     SA_SET_SYM_LNNO (def_symbol_in_progress,
668                                          (SA_GET_SYM_LNNO (def_symbol_in_progress)
669                                           + coff_line_base));
670                     break;
671 #endif
672                 }
673             }
674       }
675       break;
676 
677 #ifdef C_AUTOARG
678     case C_AUTOARG:
679 #endif /* C_AUTOARG */
680     case C_AUTO:
681     case C_REG:
682     case C_ARG:
683     case C_REGPARM:
684     case C_FIELD:
685 
686     /* According to the COFF documentation:
687 
688        http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html
689 
690        A special section number (-2) marks symbolic debugging symbols,
691        including structure/union/enumeration tag names, typedefs, and
692        the name of the file. A section number of -1 indicates that the
693        symbol has a value but is not relocatable. Examples of
694        absolute-valued symbols include automatic and register variables,
695        function arguments, and .eos symbols.
696 
697        But from Ian Lance Taylor:
698 
699        http://sources.redhat.com/ml/binutils/2000-08/msg00202.html
700 
701        the actual tools all marked them as section -1. So the GNU COFF
702        assembler follows historical COFF assemblers.
703 
704        However, it causes problems for djgpp
705 
706        http://sources.redhat.com/ml/binutils/2000-08/msg00210.html
707 
708        By defining STRICTCOFF, a COFF port can make the assembler to
709        follow the documented behavior.  */
710 #ifdef STRICTCOFF
711     case C_MOS:
712     case C_MOE:
713     case C_MOU:
714     case C_EOS:
715 #endif
716       SF_SET_DEBUG (def_symbol_in_progress);
717       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
718       break;
719 
720 #ifndef STRICTCOFF
721     case C_MOS:
722     case C_MOE:
723     case C_MOU:
724     case C_EOS:
725       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
726       break;
727 #endif
728 
729     case C_EXT:
730     case C_WEAKEXT:
731 #ifdef TE_PE
732     case C_NT_WEAK:
733 #endif
734     case C_STAT:
735     case C_LABEL:
736       /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
737       break;
738 
739     default:
740     case C_USTATIC:
741     case C_EXTDEF:
742     case C_ULABEL:
743       as_warn (_("unexpected storage class %d"),
744                  S_GET_STORAGE_CLASS (def_symbol_in_progress));
745       break;
746     }
747 
748   /* Now that we have built a debug symbol, try to find if we should
749      merge with an existing symbol or not.  If a symbol is C_EFCN or
750      absolute_section or untagged SEG_DEBUG it never merges.  We also
751      don't merge labels, which are in a different namespace, nor
752      symbols which have not yet been defined since they are typically
753      unique, nor do we merge tags with non-tags.  */
754 
755   /* Two cases for functions.  Either debug followed by definition or
756      definition followed by debug.  For definition first, we will
757      merge the debug symbol into the definition.  For debug first, the
758      lineno entry MUST point to the definition function or else it
759      will point off into space when obj_crawl_symbol_chain() merges
760      the debug symbol into the real symbol.  Therefor, let's presume
761      the debug symbol is a real function reference.  */
762 
763   /* FIXME-SOON If for some reason the definition label/symbol is
764      never seen, this will probably leave an undefined symbol at link
765      time.  */
766 
767   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
768       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
769       || (streq (bfd_section_name (S_GET_SEGMENT (def_symbol_in_progress)),
770                      "*DEBUG*")
771             && !SF_GET_TAG (def_symbol_in_progress))
772       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
773       || ! symbol_constant_p (def_symbol_in_progress)
774       || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL
775       || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
776     {
777       /* If it already is at the end of the symbol list, do nothing */
778       if (def_symbol_in_progress != symbol_lastP)
779           {
780             symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
781             symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
782                                &symbol_lastP);
783           }
784     }
785   else
786     {
787       /* This symbol already exists, merge the newly created symbol
788            into the old one.  This is not mandatory. The linker can
789            handle duplicate symbols correctly. But I guess that it save
790            a *lot* of space if the assembly file defines a lot of
791            symbols. [loic]  */
792 
793       /* The debug entry (def_symbol_in_progress) is merged into the
794            previous definition.  */
795 
796       c_symbol_merge (def_symbol_in_progress, symbolP);
797       symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
798 
799       def_symbol_in_progress = symbolP;
800 
801       if (SF_GET_FUNCTION (def_symbol_in_progress)
802             || SF_GET_TAG (def_symbol_in_progress)
803             || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
804           {
805             /* For functions, and tags, and static symbols, the symbol
806                *must* be where the debug symbol appears.  Move the
807                existing symbol to the current place.  */
808             /* If it already is at the end of the symbol list, do nothing.  */
809             if (def_symbol_in_progress != symbol_lastP)
810               {
811                 symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
812                 symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
813               }
814           }
815     }
816 
817   if (SF_GET_TAG (def_symbol_in_progress))
818     {
819       symbolS *oldtag;
820 
821       oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress));
822       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
823           tag_insert (S_GET_NAME (def_symbol_in_progress),
824                         def_symbol_in_progress);
825     }
826 
827   if (SF_GET_FUNCTION (def_symbol_in_progress))
828     {
829       set_function (def_symbol_in_progress);
830       SF_SET_PROCESS (def_symbol_in_progress);
831 
832       if (symbolP == NULL)
833           /* That is, if this is the first time we've seen the
834              function.  */
835           symbol_table_insert (def_symbol_in_progress);
836 
837     }
838 
839   def_symbol_in_progress = NULL;
840   demand_empty_rest_of_line ();
841 }
842 
843 static void
obj_coff_dim(int ignore ATTRIBUTE_UNUSED)844 obj_coff_dim (int ignore ATTRIBUTE_UNUSED)
845 {
846   int d_index;
847 
848   if (def_symbol_in_progress == NULL)
849     {
850       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
851       demand_empty_rest_of_line ();
852       return;
853     }
854 
855   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
856 
857   for (d_index = 0; d_index < DIMNUM; d_index++)
858     {
859       SKIP_WHITESPACES ();
860       SA_SET_SYM_DIMEN (def_symbol_in_progress, d_index,
861                               get_absolute_expression ());
862 
863       switch (*input_line_pointer)
864           {
865           case ',':
866             input_line_pointer++;
867             break;
868 
869           default:
870             as_warn (_("badly formed .dim directive ignored"));
871             /* Fall through.  */
872           case '\n':
873           case ';':
874             d_index = DIMNUM;
875             break;
876           }
877     }
878 
879   demand_empty_rest_of_line ();
880 }
881 
882 static void
obj_coff_line(int ignore ATTRIBUTE_UNUSED)883 obj_coff_line (int ignore ATTRIBUTE_UNUSED)
884 {
885   int this_base;
886 
887   if (def_symbol_in_progress == NULL)
888     {
889       /* Probably stabs-style line?  */
890       obj_coff_ln (0);
891       return;
892     }
893 
894   this_base = get_absolute_expression ();
895   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
896     coff_line_base = this_base;
897 
898   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
899   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
900 
901   demand_empty_rest_of_line ();
902 
903 #ifndef NO_LISTING
904   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
905     {
906       extern int listing;
907 
908       if (listing)
909           listing_source_line ((unsigned int) this_base);
910     }
911 #endif
912 }
913 
914 static void
obj_coff_size(int ignore ATTRIBUTE_UNUSED)915 obj_coff_size (int ignore ATTRIBUTE_UNUSED)
916 {
917   if (def_symbol_in_progress == NULL)
918     {
919       as_warn (_(".size pseudo-op used outside of .def/.endef: ignored."));
920       demand_empty_rest_of_line ();
921       return;
922     }
923 
924   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
925   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
926   demand_empty_rest_of_line ();
927 }
928 
929 static void
obj_coff_scl(int ignore ATTRIBUTE_UNUSED)930 obj_coff_scl (int ignore ATTRIBUTE_UNUSED)
931 {
932   if (def_symbol_in_progress == NULL)
933     {
934       as_warn (_(".scl pseudo-op used outside of .def/.endef: ignored."));
935       demand_empty_rest_of_line ();
936       return;
937     }
938 
939   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
940   demand_empty_rest_of_line ();
941 }
942 
943 static void
obj_coff_tag(int ignore ATTRIBUTE_UNUSED)944 obj_coff_tag (int ignore ATTRIBUTE_UNUSED)
945 {
946   char *symbol_name;
947   char name_end;
948 
949   if (def_symbol_in_progress == NULL)
950     {
951       as_warn (_(".tag pseudo-op used outside of .def/.endef: ignored."));
952       demand_empty_rest_of_line ();
953       return;
954     }
955 
956   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
957   name_end = get_symbol_name (&symbol_name);
958 
959 #ifdef tc_canonicalize_symbol_name
960   symbol_name = tc_canonicalize_symbol_name (symbol_name);
961 #endif
962 
963   /* Assume that the symbol referred to by .tag is always defined.
964      This was a bad assumption.  I've added find_or_make. xoxorich.  */
965   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
966                          tag_find_or_make (symbol_name));
967   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
968     as_warn (_("tag not found for .tag %s"), symbol_name);
969 
970   SF_SET_TAGGED (def_symbol_in_progress);
971 
972   (void) restore_line_pointer (name_end);
973   demand_empty_rest_of_line ();
974 }
975 
976 static void
obj_coff_type(int ignore ATTRIBUTE_UNUSED)977 obj_coff_type (int ignore ATTRIBUTE_UNUSED)
978 {
979   if (def_symbol_in_progress == NULL)
980     {
981       as_warn (_(".type pseudo-op used outside of .def/.endef: ignored."));
982       demand_empty_rest_of_line ();
983       return;
984     }
985 
986   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
987 
988   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
989       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
990     SF_SET_FUNCTION (def_symbol_in_progress);
991 
992   demand_empty_rest_of_line ();
993 }
994 
995 static void
obj_coff_val(int ignore ATTRIBUTE_UNUSED)996 obj_coff_val (int ignore ATTRIBUTE_UNUSED)
997 {
998   if (def_symbol_in_progress == NULL)
999     {
1000       as_warn (_(".val pseudo-op used outside of .def/.endef: ignored."));
1001       demand_empty_rest_of_line ();
1002       return;
1003     }
1004 
1005   if (is_name_beginner (*input_line_pointer))
1006     {
1007       char *symbol_name;
1008       char name_end = get_symbol_name (&symbol_name);
1009 
1010 #ifdef tc_canonicalize_symbol_name
1011       symbol_name = tc_canonicalize_symbol_name (symbol_name);
1012 #endif
1013       if (streq (symbol_name, "."))
1014           {
1015             /* If the .val is != from the .def (e.g. statics).  */
1016             symbol_set_frag (def_symbol_in_progress, frag_now);
1017             S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
1018           }
1019       else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name))
1020           {
1021             expressionS exp;
1022 
1023             exp.X_op = O_symbol;
1024             exp.X_add_symbol = symbol_find_or_make (symbol_name);
1025             exp.X_op_symbol = NULL;
1026             exp.X_add_number = 0;
1027             symbol_set_value_expression (def_symbol_in_progress, &exp);
1028 
1029             /* If the segment is undefined when the forward reference is
1030                resolved, then copy the segment id from the forward
1031                symbol.  */
1032             SF_SET_GET_SEGMENT (def_symbol_in_progress);
1033 
1034             /* FIXME: gcc can generate address expressions here in
1035                unusual cases (search for "obscure" in sdbout.c).  We
1036                just ignore the offset here, thus generating incorrect
1037                debugging information.  We ignore the rest of the line
1038                just below.  */
1039           }
1040       /* Otherwise, it is the name of a non debug symbol and its value
1041          will be calculated later.  */
1042       (void) restore_line_pointer (name_end);
1043     }
1044   else
1045     {
1046       S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
1047     }
1048 
1049   demand_empty_rest_of_line ();
1050 }
1051 
1052 #ifdef TE_PE
1053 
1054 /* Return nonzero if name begins with weak alternate symbol prefix.  */
1055 
1056 static int
weak_is_altname(const char * name)1057 weak_is_altname (const char * name)
1058 {
1059   return startswith (name, weak_altprefix);
1060 }
1061 
1062 /* Return the name of the alternate symbol
1063    name corresponding to a weak symbol's name.  */
1064 
1065 static const char *
weak_name2altname(const char * name)1066 weak_name2altname (const char * name)
1067 {
1068   return concat (weak_altprefix, name, (char *) NULL);
1069 }
1070 
1071 /* Return the name of the weak symbol corresponding to an
1072    alternate symbol.  */
1073 
1074 static const char *
weak_altname2name(const char * name)1075 weak_altname2name (const char * name)
1076 {
1077   gas_assert (weak_is_altname (name));
1078   return xstrdup (name + 6);
1079 }
1080 
1081 /* Make a weak symbol name unique by
1082    appending the name of an external symbol.  */
1083 
1084 static const char *
weak_uniquify(const char * name)1085 weak_uniquify (const char * name)
1086 {
1087   const char * unique = "";
1088 
1089 #ifdef TE_PE
1090   if (an_external_name != NULL)
1091     unique = an_external_name;
1092 #endif
1093   gas_assert (weak_is_altname (name));
1094 
1095   return concat (name, ".", unique, (char *) NULL);
1096 }
1097 
1098 void
pecoff_obj_set_weak_hook(symbolS * symbolP)1099 pecoff_obj_set_weak_hook (symbolS *symbolP)
1100 {
1101   symbolS *alternateP;
1102 
1103   /* See _Microsoft Portable Executable and Common Object
1104      File Format Specification_, section 5.5.3.
1105      Create a symbol representing the alternate value.
1106      coff_frob_symbol will set the value of this symbol from
1107      the value of the weak symbol itself.  */
1108   S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
1109   S_SET_NUMBER_AUXILIARY (symbolP, 1);
1110   SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
1111 
1112   alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
1113   S_SET_EXTERNAL (alternateP);
1114   S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
1115 
1116   SA_SET_SYM_TAGNDX (symbolP, alternateP);
1117 }
1118 
1119 void
pecoff_obj_clear_weak_hook(symbolS * symbolP)1120 pecoff_obj_clear_weak_hook (symbolS *symbolP)
1121 {
1122   symbolS *alternateP;
1123 
1124   S_SET_STORAGE_CLASS (symbolP, 0);
1125   SA_SET_SYM_FSIZE (symbolP, 0);
1126 
1127   alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
1128   S_CLEAR_EXTERNAL (alternateP);
1129 }
1130 
1131 #endif  /* TE_PE */
1132 
1133 /* Handle .weak.  This is a GNU extension in formats other than PE. */
1134 
1135 static void
obj_coff_weak(int ignore ATTRIBUTE_UNUSED)1136 obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
1137 {
1138   char *name;
1139   int c;
1140   symbolS *symbolP;
1141 
1142   do
1143     {
1144       c = get_symbol_name (&name);
1145       if (*name == 0)
1146           {
1147             as_warn (_("badly formed .weak directive ignored"));
1148             ignore_rest_of_line ();
1149             return;
1150           }
1151       c = 0;
1152       symbolP = symbol_find_or_make (name);
1153       *input_line_pointer = c;
1154       SKIP_WHITESPACE_AFTER_NAME ();
1155       S_SET_WEAK (symbolP);
1156 
1157       if (c == ',')
1158           {
1159             input_line_pointer++;
1160             SKIP_WHITESPACE ();
1161             if (*input_line_pointer == '\n')
1162               c = '\n';
1163           }
1164 
1165     }
1166   while (c == ',');
1167 
1168   demand_empty_rest_of_line ();
1169 }
1170 
1171 void
coff_obj_read_begin_hook(void)1172 coff_obj_read_begin_hook (void)
1173 {
1174   /* These had better be the same.  Usually 18 bytes.  */
1175   know (sizeof (SYMENT) == sizeof (AUXENT));
1176   know (SYMESZ == AUXESZ);
1177   tag_init ();
1178 }
1179 
1180 symbolS *coff_last_function;
1181 #ifndef OBJ_XCOFF
1182 static symbolS *coff_last_bf;
1183 #endif
1184 
1185 void
coff_frob_symbol(symbolS * symp,int * punt)1186 coff_frob_symbol (symbolS *symp, int *punt)
1187 {
1188   static symbolS *last_tagP;
1189   static stack *block_stack;
1190   static symbolS *set_end;
1191   symbolS *next_set_end = NULL;
1192 
1193   if (symp == &abs_symbol)
1194     {
1195       *punt = 1;
1196       return;
1197     }
1198 
1199   if (current_lineno_sym)
1200     coff_add_linesym (NULL);
1201 
1202   if (!block_stack)
1203     block_stack = stack_init (512, sizeof (symbolS*));
1204 
1205 #ifdef TE_PE
1206   if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
1207       && ! S_IS_WEAK (symp)
1208       && weak_is_altname (S_GET_NAME (symp)))
1209     {
1210       /* This is a weak alternate symbol.  All processing of
1211            PECOFFweak symbols is done here, through the alternate.  */
1212       symbolS *weakp = symbol_find_noref (weak_altname2name
1213                                                     (S_GET_NAME (symp)), 1);
1214 
1215       gas_assert (weakp);
1216       gas_assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
1217 
1218       if (! S_IS_WEAK (weakp))
1219           {
1220             /* The symbol was turned from weak to strong.  Discard altname.  */
1221             *punt = 1;
1222             return;
1223           }
1224       else if (symbol_equated_p (weakp))
1225           {
1226             /* The weak symbol has an alternate specified; symp is unneeded.  */
1227             S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
1228             SA_SET_SYM_TAGNDX (weakp,
1229               symbol_get_value_expression (weakp)->X_add_symbol);
1230 
1231             S_CLEAR_EXTERNAL (symp);
1232             *punt = 1;
1233             return;
1234           }
1235       else
1236           {
1237             /* The weak symbol has been assigned an alternate value.
1238              Copy this value to symp, and set symp as weakp's alternate.  */
1239             if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
1240               {
1241                 S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
1242                 S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
1243               }
1244 
1245             if (S_IS_DEFINED (weakp))
1246               {
1247                 /* This is a defined weak symbol.  Copy value information
1248                    from the weak symbol itself to the alternate symbol.  */
1249                 symbol_set_value_expression (symp,
1250                                                      symbol_get_value_expression (weakp));
1251                 symbol_set_frag (symp, symbol_get_frag (weakp));
1252                 S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
1253               }
1254             else
1255               {
1256                 /* This is an undefined weak symbol.
1257                      Define the alternate symbol to zero.  */
1258                 S_SET_VALUE (symp, 0);
1259                 S_SET_SEGMENT (symp, absolute_section);
1260               }
1261 
1262             S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
1263             S_SET_STORAGE_CLASS (symp, C_EXT);
1264 
1265             S_SET_VALUE (weakp, 0);
1266             S_SET_SEGMENT (weakp, undefined_section);
1267           }
1268     }
1269 #else /* TE_PE */
1270   if (S_IS_WEAK (symp))
1271     S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
1272 #endif /* TE_PE */
1273 
1274   if (!S_IS_DEFINED (symp)
1275       && !S_IS_WEAK (symp)
1276       && S_GET_STORAGE_CLASS (symp) != C_STAT)
1277     S_SET_STORAGE_CLASS (symp, C_EXT);
1278 
1279   if (!SF_GET_DEBUG (symp))
1280     {
1281       symbolS * real;
1282 
1283       if (!SF_GET_LOCAL (symp)
1284             && !SF_GET_STATICS (symp)
1285             && S_GET_STORAGE_CLASS (symp) != C_LABEL
1286             && symbol_constant_p (symp)
1287             && (real = symbol_find_noref (S_GET_NAME (symp), 1))
1288             && S_GET_STORAGE_CLASS (real) == C_NULL
1289             && real != symp)
1290           {
1291             c_symbol_merge (symp, real);
1292             *punt = 1;
1293             return;
1294           }
1295 
1296       if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
1297           {
1298             gas_assert (S_GET_VALUE (symp) == 0);
1299             if (S_IS_WEAKREFD (symp))
1300               *punt = 1;
1301             else
1302               S_SET_EXTERNAL (symp);
1303           }
1304       else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
1305           {
1306             if (S_GET_SEGMENT (symp) == text_section
1307                 && symp != seg_info (text_section)->sym)
1308               S_SET_STORAGE_CLASS (symp, C_LABEL);
1309             else
1310               S_SET_STORAGE_CLASS (symp, C_STAT);
1311           }
1312 
1313       if (SF_GET_PROCESS (symp))
1314           {
1315             if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
1316               {
1317                 if (streq (S_GET_NAME (symp), ".bb"))
1318                     stack_push (block_stack, (char *) &symp);
1319                 else
1320                     {
1321                       symbolS *begin;
1322 
1323                       begin = *(symbolS **) stack_pop (block_stack);
1324                       if (begin == 0)
1325                         as_warn (_("mismatched .eb"));
1326                       else
1327                         next_set_end = begin;
1328                     }
1329               }
1330 
1331             if (coff_last_function == 0 && SF_GET_FUNCTION (symp)
1332                 && S_IS_DEFINED (symp))
1333               {
1334                 union internal_auxent *auxp;
1335 
1336                 coff_last_function = symp;
1337                 if (S_GET_NUMBER_AUXILIARY (symp) < 1)
1338                     S_SET_NUMBER_AUXILIARY (symp, 1);
1339                 auxp = SYM_AUXENT (symp);
1340                 memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
1341                           sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
1342               }
1343 
1344             if (S_GET_STORAGE_CLASS (symp) == C_EFCN
1345                 && S_IS_DEFINED (symp))
1346               {
1347                 if (coff_last_function == 0)
1348                     as_fatal (_("C_EFCN symbol for %s out of scope"),
1349                                 S_GET_NAME (symp));
1350                 SA_SET_SYM_FSIZE (coff_last_function,
1351                                         (long) (S_GET_VALUE (symp)
1352                                                   - S_GET_VALUE (coff_last_function)));
1353                 next_set_end = coff_last_function;
1354                 coff_last_function = 0;
1355               }
1356           }
1357 
1358       if (S_IS_EXTERNAL (symp))
1359           S_SET_STORAGE_CLASS (symp, C_EXT);
1360       else if (SF_GET_LOCAL (symp))
1361           *punt = 1;
1362 
1363       if (SF_GET_FUNCTION (symp))
1364           symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
1365     }
1366 
1367   /* Double check weak symbols.  */
1368   if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
1369     as_bad (_("Symbol `%s' can not be both weak and common"),
1370               S_GET_NAME (symp));
1371 
1372   if (SF_GET_TAG (symp))
1373     last_tagP = symp;
1374   else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
1375     next_set_end = last_tagP;
1376 
1377 #ifdef OBJ_XCOFF
1378   /* This is pretty horrible, but we have to set *punt correctly in
1379      order to call SA_SET_SYM_ENDNDX correctly.  */
1380   if (! symbol_used_in_reloc_p (symp)
1381       && S_GET_STORAGE_CLASS (symp) != C_DWARF
1382       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
1383             || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
1384                 && ! symbol_get_tc (symp)->output
1385                 && S_GET_STORAGE_CLASS (symp) != C_FILE)))
1386     *punt = 1;
1387 #endif
1388 
1389   if (set_end != (symbolS *) NULL
1390       && ! *punt
1391       && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
1392             || (S_IS_DEFINED (symp)
1393                 && ! S_IS_COMMON (symp)
1394                 && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
1395     {
1396       SA_SET_SYM_ENDNDX (set_end, symp);
1397       set_end = NULL;
1398     }
1399 
1400   if (next_set_end != NULL)
1401     {
1402       if (set_end != NULL)
1403           as_warn (_("Warning: internal error: forgetting to set endndx of %s"),
1404                      S_GET_NAME (set_end));
1405       set_end = next_set_end;
1406     }
1407 
1408 #ifndef OBJ_XCOFF
1409   if (! *punt
1410       && S_GET_STORAGE_CLASS (symp) == C_FCN
1411       && streq (S_GET_NAME (symp), ".bf"))
1412     {
1413       if (coff_last_bf != NULL)
1414           SA_SET_SYM_ENDNDX (coff_last_bf, symp);
1415       coff_last_bf = symp;
1416     }
1417 #endif
1418   if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
1419     {
1420       int i;
1421       struct line_no *lptr;
1422       alent *l;
1423 
1424       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
1425       for (i = 0; lptr; lptr = lptr->next)
1426           i++;
1427       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
1428 
1429       /* We need i entries for line numbers, plus 1 for the first
1430            entry which BFD will override, plus 1 for the last zero
1431            entry (a marker for BFD).  */
1432       l = XNEWVEC (alent, (i + 2));
1433       coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
1434       l[i + 1].line_number = 0;
1435       l[i + 1].u.sym = NULL;
1436       for (; i > 0; i--)
1437           {
1438             if (lptr->frag)
1439               lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
1440             l[i] = lptr->l;
1441             lptr = lptr->next;
1442           }
1443     }
1444 }
1445 
1446 void
coff_adjust_section_syms(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * x ATTRIBUTE_UNUSED)1447 coff_adjust_section_syms (bfd *abfd ATTRIBUTE_UNUSED,
1448                                 asection *sec,
1449                                 void * x ATTRIBUTE_UNUSED)
1450 {
1451   symbolS *secsym;
1452   segment_info_type *seginfo = seg_info (sec);
1453   int nlnno, nrelocs = 0;
1454 
1455   /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
1456      tc-ppc.c.  Do not get confused by it.  */
1457   if (seginfo == NULL)
1458     return;
1459 
1460   if (streq (sec->name, ".text"))
1461     nlnno = coff_n_line_nos;
1462   else
1463     nlnno = 0;
1464   {
1465     /* @@ Hope that none of the fixups expand to more than one reloc
1466        entry...  */
1467     fixS *fixp = seginfo->fix_root;
1468     while (fixp)
1469       {
1470           if (! fixp->fx_done)
1471             nrelocs++;
1472           fixp = fixp->fx_next;
1473       }
1474   }
1475   if (bfd_section_size (sec) == 0
1476       && nrelocs == 0
1477       && nlnno == 0
1478       && sec != text_section
1479       && sec != data_section
1480       && sec != bss_section)
1481     return;
1482 
1483   secsym = section_symbol (sec);
1484   /* This is an estimate; we'll plug in the real value using
1485      SET_SECTION_RELOCS later */
1486 #ifdef OBJ_XCOFF
1487   if (S_GET_STORAGE_CLASS (secsym) == C_DWARF)
1488     SA_SET_SECT_NRELOC (secsym, nrelocs);
1489   else
1490     {
1491       SA_SET_SCN_NRELOC (secsym, nrelocs);
1492       SA_SET_SCN_NLINNO (secsym, nlnno);
1493     }
1494 #else
1495   SA_SET_SCN_NRELOC (secsym, nrelocs);
1496   SA_SET_SCN_NLINNO (secsym, nlnno);
1497 #endif
1498 }
1499 
1500 void
coff_frob_file_after_relocs(void)1501 coff_frob_file_after_relocs (void)
1502 {
1503   bfd_map_over_sections (stdoutput, coff_adjust_section_syms, NULL);
1504 }
1505 
1506 /* Implement the .section pseudo op:
1507           .section name {, "flags"}
1508                   ^         ^
1509                   |         +--- optional flags: 'b' for bss
1510                   |                              'i' for info
1511                   +-- section name               'l' for lib
1512                                                  'n' for noload
1513                                                  'o' for over
1514                                                  'w' for data
1515                                                              'd' (apparently m88k for data)
1516                                                              'e' for exclude
1517                                                  'x' for text
1518                                                              'r' for read-only data
1519                                                              's' for shared data (PE)
1520                                                              'y' for noread
1521                                                      '0' - '9' for power-of-two alignment (GNU extension).
1522    But if the argument is not a quoted string, treat it as a
1523    subsegment number.
1524 
1525    Note the 'a' flag is silently ignored.  This allows the same
1526    .section directive to be parsed in both ELF and COFF formats.  */
1527 
1528 void
obj_coff_section(int ignore ATTRIBUTE_UNUSED)1529 obj_coff_section (int ignore ATTRIBUTE_UNUSED)
1530 {
1531   /* Strip out the section name.  */
1532   char *section_name;
1533   char c;
1534   int alignment = -1;
1535   char *name;
1536   unsigned int exp;
1537   flagword flags, oldflags;
1538   asection *sec;
1539   bool is_bss = false;
1540 
1541   if (flag_mri)
1542     {
1543       char type;
1544 
1545       s_mri_sect (&type);
1546       return;
1547     }
1548 
1549   c = get_symbol_name (&section_name);
1550   name = xmemdup0 (section_name, input_line_pointer - section_name);
1551   *input_line_pointer = c;
1552   SKIP_WHITESPACE_AFTER_NAME ();
1553 
1554   exp = 0;
1555   flags = SEC_NO_FLAGS;
1556 
1557   if (*input_line_pointer == ',')
1558     {
1559       ++input_line_pointer;
1560       SKIP_WHITESPACE ();
1561       if (*input_line_pointer != '"')
1562           exp = get_absolute_expression ();
1563       else
1564           {
1565             unsigned char attr;
1566             int readonly_removed = 0;
1567             int load_removed = 0;
1568 
1569             while (attr = *++input_line_pointer,
1570                      attr != '"'
1571                      && ! is_end_of_line[attr])
1572               {
1573                 if (ISDIGIT (attr))
1574                     {
1575                       alignment = attr - '0';
1576                       continue;
1577                     }
1578                 switch (attr)
1579                     {
1580                     case 'e':
1581                       /* Exclude section from linking.  */
1582                       flags |= SEC_EXCLUDE;
1583                       break;
1584 
1585                     case 'b':
1586                       /* Uninitialised data section.  */
1587                       flags |= SEC_ALLOC;
1588                       flags &=~ SEC_LOAD;
1589                       is_bss = true;
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 (is_bss)
1662     seg_info (sec)->bss = 1;
1663 
1664   if (alignment >= 0)
1665     sec->alignment_power = alignment;
1666 
1667   oldflags = bfd_section_flags (sec);
1668   if (oldflags == SEC_NO_FLAGS)
1669     {
1670       /* Set section flags for a new section just created by subseg_new.
1671          Provide a default if no flags were parsed.  */
1672       if (flags == SEC_NO_FLAGS)
1673           flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;
1674 
1675 #ifdef COFF_LONG_SECTION_NAMES
1676       /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce
1677          sections so adjust_reloc_syms in write.c will correctly handle
1678          relocs which refer to non-local symbols in these sections.  */
1679       if (startswith (name, ".gnu.linkonce"))
1680           flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
1681 #endif
1682 
1683       if (!bfd_set_section_flags (sec, flags))
1684           as_warn (_("error setting flags for \"%s\": %s"),
1685                      bfd_section_name (sec),
1686                      bfd_errmsg (bfd_get_error ()));
1687     }
1688   else if (flags != SEC_NO_FLAGS)
1689     {
1690       /* This section's attributes have already been set.  Warn if the
1691          attributes don't match.  */
1692       flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
1693                                    | SEC_DATA | SEC_COFF_SHARED | SEC_NEVER_LOAD
1694                                    | SEC_COFF_NOREAD);
1695       if ((flags ^ oldflags) & matchflags)
1696           as_warn (_("Ignoring changed section attributes for %s"), name);
1697     }
1698 
1699   demand_empty_rest_of_line ();
1700 }
1701 
1702 void
coff_adjust_symtab(void)1703 coff_adjust_symtab (void)
1704 {
1705   if (symbol_rootP == NULL
1706       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
1707     c_dot_file_symbol ("fake");
1708 }
1709 
1710 void
coff_frob_section(segT sec)1711 coff_frob_section (segT sec)
1712 {
1713   segT strsec;
1714   char *p;
1715   fragS *fragp;
1716   bfd_vma n_entries;
1717 
1718   /* The COFF back end in BFD requires that all section sizes be
1719      rounded up to multiples of the corresponding section alignments,
1720      supposedly because standard COFF has no other way of encoding alignment
1721      for sections.  If your COFF flavor has a different way of encoding
1722      section alignment, then skip this step, as TICOFF does.  */
1723   bfd_vma size = bfd_section_size (sec);
1724 #if !defined(TICOFF)
1725   bfd_vma align_power = (bfd_vma) sec->alignment_power + OCTETS_PER_BYTE_POWER;
1726   bfd_vma mask = ((bfd_vma) 1 << align_power) - 1;
1727 
1728   if (!do_not_pad_sections_to_alignment
1729       && (size & mask) != 0)
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       if ((new_size - size) % fragp->fr_var == 0)
1745           fragp->fr_offset += (new_size - size) / fragp->fr_var;
1746       else
1747           abort ();
1748     }
1749 #endif
1750 
1751   /* If the section size is non-zero, the section symbol needs an aux
1752      entry associated with it, indicating the size.  We don't know
1753      all the values yet; coff_frob_symbol will fill them in later.  */
1754 #ifndef TICOFF
1755   if (size != 0
1756       || sec == text_section
1757       || sec == data_section
1758       || sec == bss_section)
1759 #endif
1760     {
1761       symbolS *secsym = section_symbol (sec);
1762       unsigned char sclass = C_STAT;
1763 
1764 #ifdef OBJ_XCOFF
1765       if (bfd_section_flags (sec) & SEC_DEBUGGING)
1766         sclass = C_DWARF;
1767 #endif
1768       S_SET_STORAGE_CLASS (secsym, sclass);
1769       S_SET_NUMBER_AUXILIARY (secsym, 1);
1770       SF_SET_STATICS (secsym);
1771 #ifdef OBJ_XCOFF
1772       SA_SET_SECT_SCNLEN (secsym, size);
1773 #else
1774       SA_SET_SCN_SCNLEN (secsym, size);
1775 #endif
1776     }
1777   /* FIXME: These should be in a "stabs.h" file, or maybe as.h.  */
1778 #ifndef STAB_SECTION_NAME
1779 #define STAB_SECTION_NAME ".stab"
1780 #endif
1781 #ifndef STAB_STRING_SECTION_NAME
1782 #define STAB_STRING_SECTION_NAME ".stabstr"
1783 #endif
1784   if (! streq (STAB_STRING_SECTION_NAME, sec->name))
1785     return;
1786 
1787   strsec = sec;
1788   sec = subseg_get (STAB_SECTION_NAME, 0);
1789   /* size is already rounded up, since other section will be listed first */
1790   size = bfd_section_size (strsec);
1791 
1792   n_entries = bfd_section_size (sec) / 12 - 1;
1793 
1794   /* Find first non-empty frag.  It should be large enough.  */
1795   fragp = seg_info (sec)->frchainP->frch_root;
1796   while (fragp && fragp->fr_fix == 0)
1797     fragp = fragp->fr_next;
1798   gas_assert (fragp != 0 && fragp->fr_fix >= 12);
1799 
1800   /* Store the values.  */
1801   p = fragp->fr_literal;
1802   bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
1803   bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
1804 }
1805 
1806 void
obj_coff_init_stab_section(segT stab ATTRIBUTE_UNUSED,segT stabstr)1807 obj_coff_init_stab_section (segT stab ATTRIBUTE_UNUSED, segT stabstr)
1808 {
1809   const char *file;
1810   char *p;
1811   unsigned int stroff;
1812 
1813   /* Make space for this first symbol.  */
1814   p = frag_more (12);
1815   /* Zero it out.  */
1816   memset (p, 0, 12);
1817   file = as_where ((unsigned int *) NULL);
1818   stroff = get_stab_string_offset (file, stabstr);
1819   know (stroff == 1);
1820   md_number_to_chars (p, stroff, 4);
1821 }
1822 
1823 #ifdef DEBUG
1824 const char * s_get_name (symbolS *);
1825 
1826 const char *
s_get_name(symbolS * s)1827 s_get_name (symbolS *s)
1828 {
1829   return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
1830 }
1831 
1832 void symbol_dump (void);
1833 
1834 void
symbol_dump(void)1835 symbol_dump (void)
1836 {
1837   symbolS *symbolP;
1838 
1839   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
1840     printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
1841               (unsigned long) symbolP,
1842               S_GET_NAME (symbolP),
1843               (long) S_GET_DATA_TYPE (symbolP),
1844               S_GET_STORAGE_CLASS (symbolP),
1845               (int) S_GET_SEGMENT (symbolP));
1846 }
1847 
1848 #endif /* DEBUG */
1849 
1850 const pseudo_typeS coff_pseudo_table[] =
1851 {
1852   {"ABORT", s_abort, 0},
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   0,      /* end.  */
1912   c_dot_file_symbol,
1913   coff_frob_symbol,
1914   0,      /* frob_file */
1915   0,      /* frob_file_before_adjust */
1916   0,      /* frob_file_before_fix */
1917   coff_frob_file_after_relocs,
1918   0,      /* s_get_size */
1919   0,      /* s_set_size */
1920   0,      /* s_get_align */
1921   0,      /* s_set_align */
1922   0,      /* s_get_other */
1923   0,      /* s_set_other */
1924   0,      /* s_get_desc */
1925   0,      /* s_set_desc */
1926   0,      /* s_get_type */
1927   0,      /* s_set_type */
1928   0,      /* copy_symbol_attributes */
1929   0,      /* generate_asm_lineno */
1930   0,      /* process_stab */
1931   coff_separate_stab_sections,
1932   obj_coff_init_stab_section,
1933   0,      /* sec_sym_ok_for_reloc */
1934   coff_pop_insert,
1935   0,      /* ecoff_set_ext */
1936   coff_obj_read_begin_hook,
1937   coff_obj_symbol_new_hook,
1938   coff_obj_symbol_clone_hook,
1939   coff_adjust_symtab
1940 };
1941