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