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