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