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