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