133965Sjdp/* coff object file format 278828Sobrien Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3218822Sdim 1999, 2000, 2001, 2002, 2003, 2004, 2005 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS. 733965Sjdp 833965Sjdp GAS is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2, or (at your option) 1133965Sjdp any later version. 1233965Sjdp 1333965Sjdp GAS is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with GAS; see the file COPYING. If not, write to the Free 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 2333965Sjdp#define OBJ_HEADER "obj-coff.h" 2433965Sjdp 2533965Sjdp#include "as.h" 2633965Sjdp#include "obstack.h" 2733965Sjdp#include "subsegs.h" 2833965Sjdp 29218822Sdim#ifdef TE_PE 30218822Sdim#include "coff/pe.h" 31218822Sdim#endif 32218822Sdim 33218822Sdim#define streq(a,b) (strcmp ((a), (b)) == 0) 34218822Sdim#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) 35218822Sdim 3633965Sjdp/* I think this is probably always correct. */ 3733965Sjdp#ifndef KEEP_RELOC_INFO 3833965Sjdp#define KEEP_RELOC_INFO 3933965Sjdp#endif 4033965Sjdp 41218822Sdim/* obj_coff_section will use this macro to set a new section's 42218822Sdim attributes when a directive has no valid flags or the "w" flag is 43218822Sdim used. This default should be appropriate for most. */ 4477298Sobrien#ifndef TC_COFF_SECTION_DEFAULT_ATTRIBUTES 4577298Sobrien#define TC_COFF_SECTION_DEFAULT_ATTRIBUTES (SEC_LOAD | SEC_DATA) 4677298Sobrien#endif 4777298Sobrien 4889857Sobrien/* This is used to hold the symbol built by a sequence of pseudo-ops 4989857Sobrien from .def and .endef. */ 5089857Sobrienstatic symbolS *def_symbol_in_progress; 51218822Sdim#ifdef TE_PE 52218822Sdim/* PE weak alternate symbols begin with this string. */ 53218822Sdimstatic const char weak_altprefix[] = ".weak."; 54218822Sdim#endif /* TE_PE */ 5589857Sobrien 5689857Sobrientypedef struct 5789857Sobrien { 5889857Sobrien unsigned long chunk_size; 5989857Sobrien unsigned long element_size; 6089857Sobrien unsigned long size; 6189857Sobrien char *data; 6289857Sobrien unsigned long pointer; 6389857Sobrien } 6489857Sobrienstack; 6589857Sobrien 6633965Sjdp 67218822Sdim/* Stack stuff. */ 6833965Sjdp 6933965Sjdpstatic stack * 70218822Sdimstack_init (unsigned long chunk_size, 71218822Sdim unsigned long element_size) 7233965Sjdp{ 7333965Sjdp stack *st; 7433965Sjdp 75218822Sdim st = malloc (sizeof (* st)); 7633965Sjdp if (!st) 77218822Sdim return NULL; 7833965Sjdp st->data = malloc (chunk_size); 7933965Sjdp if (!st->data) 8033965Sjdp { 8133965Sjdp free (st); 82218822Sdim return NULL; 8333965Sjdp } 8433965Sjdp st->pointer = 0; 8533965Sjdp st->size = chunk_size; 8633965Sjdp st->chunk_size = chunk_size; 8733965Sjdp st->element_size = element_size; 8833965Sjdp return st; 8933965Sjdp} 9033965Sjdp 9133965Sjdpstatic char * 92218822Sdimstack_push (stack *st, char *element) 9333965Sjdp{ 9433965Sjdp if (st->pointer + st->element_size >= st->size) 9533965Sjdp { 9633965Sjdp st->size += st->chunk_size; 97218822Sdim if ((st->data = xrealloc (st->data, st->size)) == NULL) 98218822Sdim return NULL; 9933965Sjdp } 10033965Sjdp memcpy (st->data + st->pointer, element, st->element_size); 10133965Sjdp st->pointer += st->element_size; 10233965Sjdp return st->data + st->pointer; 10333965Sjdp} 10433965Sjdp 10533965Sjdpstatic char * 106218822Sdimstack_pop (stack *st) 10733965Sjdp{ 10833965Sjdp if (st->pointer < st->element_size) 10933965Sjdp { 11033965Sjdp st->pointer = 0; 111218822Sdim return NULL; 11233965Sjdp } 11333965Sjdp st->pointer -= st->element_size; 11433965Sjdp return st->data + st->pointer; 11533965Sjdp} 11633965Sjdp 117218822Sdim/* Maintain a list of the tagnames of the structures. */ 11833965Sjdp 11933965Sjdpstatic struct hash_control *tag_hash; 12033965Sjdp 12133965Sjdpstatic void 122218822Sdimtag_init (void) 12333965Sjdp{ 12433965Sjdp tag_hash = hash_new (); 12533965Sjdp} 12633965Sjdp 12733965Sjdpstatic void 128218822Sdimtag_insert (const char *name, symbolS *symbolP) 12933965Sjdp{ 13033965Sjdp const char *error_string; 13133965Sjdp 13233965Sjdp if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) 133218822Sdim as_fatal (_("Inserting \"%s\" into structure table failed: %s"), 134218822Sdim name, error_string); 13533965Sjdp} 13633965Sjdp 13733965Sjdpstatic symbolS * 138218822Sdimtag_find (char *name) 13933965Sjdp{ 14033965Sjdp return (symbolS *) hash_find (tag_hash, name); 14133965Sjdp} 14233965Sjdp 14333965Sjdpstatic symbolS * 144218822Sdimtag_find_or_make (char *name) 14533965Sjdp{ 14633965Sjdp symbolS *symbolP; 14733965Sjdp 14833965Sjdp if ((symbolP = tag_find (name)) == NULL) 14933965Sjdp { 15033965Sjdp symbolP = symbol_new (name, undefined_section, 15133965Sjdp 0, &zero_address_frag); 15233965Sjdp 15333965Sjdp tag_insert (S_GET_NAME (symbolP), symbolP); 15433965Sjdp symbol_table_insert (symbolP); 155218822Sdim } 15633965Sjdp 15733965Sjdp return symbolP; 15833965Sjdp} 15933965Sjdp 16038889Sjdp/* We accept the .bss directive to set the section for backward 16138889Sjdp compatibility with earlier versions of gas. */ 16233965Sjdp 16338889Sjdpstatic void 164218822Sdimobj_coff_bss (int ignore ATTRIBUTE_UNUSED) 16538889Sjdp{ 16638889Sjdp if (*input_line_pointer == '\n') 16738889Sjdp subseg_new (".bss", get_absolute_expression ()); 16838889Sjdp else 16938889Sjdp s_lcomm (0); 17038889Sjdp} 17133965Sjdp 17233965Sjdp#define GET_FILENAME_STRING(X) \ 173218822Sdim ((char *) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1]) 17433965Sjdp 17533965Sjdp/* @@ Ick. */ 17633965Sjdpstatic segT 177218822Sdimfetch_coff_debug_section (void) 17833965Sjdp{ 17933965Sjdp static segT debug_section; 180218822Sdim 18133965Sjdp if (!debug_section) 18233965Sjdp { 183104834Sobrien const asymbol *s; 184218822Sdim 185218822Sdim s = bfd_make_debug_symbol (stdoutput, NULL, 0); 18633965Sjdp assert (s != 0); 18733965Sjdp debug_section = s->section; 18833965Sjdp } 18933965Sjdp return debug_section; 19033965Sjdp} 19133965Sjdp 19233965Sjdpvoid 193218822SdimSA_SET_SYM_ENDNDX (symbolS *sym, symbolS *val) 19433965Sjdp{ 19533965Sjdp combined_entry_type *entry, *p; 19633965Sjdp 19760484Sobrien entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1]; 19860484Sobrien p = coffsymbol (symbol_get_bfdsym (val))->native; 19933965Sjdp entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p; 20033965Sjdp entry->fix_end = 1; 20133965Sjdp} 20233965Sjdp 20333965Sjdpstatic void 204218822SdimSA_SET_SYM_TAGNDX (symbolS *sym, symbolS *val) 20533965Sjdp{ 20633965Sjdp combined_entry_type *entry, *p; 20733965Sjdp 20860484Sobrien entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1]; 20960484Sobrien p = coffsymbol (symbol_get_bfdsym (val))->native; 21033965Sjdp entry->u.auxent.x_sym.x_tagndx.p = p; 21133965Sjdp entry->fix_tag = 1; 21233965Sjdp} 21333965Sjdp 21433965Sjdpstatic int 215218822SdimS_GET_DATA_TYPE (symbolS *sym) 21633965Sjdp{ 21760484Sobrien return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type; 21833965Sjdp} 21933965Sjdp 22033965Sjdpint 221218822SdimS_SET_DATA_TYPE (symbolS *sym, int val) 22233965Sjdp{ 22360484Sobrien coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type = val; 22433965Sjdp return val; 22533965Sjdp} 22633965Sjdp 22733965Sjdpint 228218822SdimS_GET_STORAGE_CLASS (symbolS *sym) 22933965Sjdp{ 23060484Sobrien return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass; 23133965Sjdp} 23233965Sjdp 23333965Sjdpint 234218822SdimS_SET_STORAGE_CLASS (symbolS *sym, int val) 23533965Sjdp{ 23660484Sobrien coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass = val; 23733965Sjdp return val; 23833965Sjdp} 23933965Sjdp 24077298Sobrien/* Merge a debug symbol containing debug information into a normal symbol. */ 24133965Sjdp 242218822Sdimstatic void 243218822Sdimc_symbol_merge (symbolS *debug, symbolS *normal) 24433965Sjdp{ 24533965Sjdp S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); 24633965Sjdp S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); 24733965Sjdp 24833965Sjdp if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) 249218822Sdim /* Take the most we have. */ 250218822Sdim S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); 25133965Sjdp 25233965Sjdp if (S_GET_NUMBER_AUXILIARY (debug) > 0) 253218822Sdim /* Move all the auxiliary information. */ 254218822Sdim memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug), 255218822Sdim (S_GET_NUMBER_AUXILIARY (debug) 256218822Sdim * sizeof (*SYM_AUXINFO (debug)))); 25733965Sjdp 25877298Sobrien /* Move the debug flags. */ 25933965Sjdp SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); 26033965Sjdp} 26133965Sjdp 26233965Sjdpvoid 263218822Sdimc_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED) 26433965Sjdp{ 26533965Sjdp symbolS *symbolP; 26633965Sjdp 26760484Sobrien /* BFD converts filename to a .file symbol with an aux entry. It 26860484Sobrien also handles chaining. */ 26933965Sjdp symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag); 27033965Sjdp 27133965Sjdp S_SET_STORAGE_CLASS (symbolP, C_FILE); 27233965Sjdp S_SET_NUMBER_AUXILIARY (symbolP, 1); 27333965Sjdp 27460484Sobrien symbol_get_bfdsym (symbolP)->flags = BSF_DEBUGGING; 27533965Sjdp 27633965Sjdp#ifndef NO_LISTING 27733965Sjdp { 27833965Sjdp extern int listing; 279218822Sdim 28033965Sjdp if (listing) 281218822Sdim listing_source_file (filename); 28233965Sjdp } 28333965Sjdp#endif 28433965Sjdp 285218822Sdim /* Make sure that the symbol is first on the symbol chain. */ 28633965Sjdp if (symbol_rootP != symbolP) 28733965Sjdp { 28833965Sjdp symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); 28933965Sjdp symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); 290218822Sdim } 29133965Sjdp} 29233965Sjdp 293218822Sdim/* Line number handling. */ 29433965Sjdp 295218822Sdimstruct line_no 296218822Sdim{ 29733965Sjdp struct line_no *next; 29833965Sjdp fragS *frag; 29933965Sjdp alent l; 30033965Sjdp}; 30133965Sjdp 30233965Sjdpint coff_line_base; 30333965Sjdp 30433965Sjdp/* Symbol of last function, which we should hang line#s off of. */ 30533965Sjdpstatic symbolS *line_fsym; 30633965Sjdp 30733965Sjdp#define in_function() (line_fsym != 0) 30833965Sjdp#define clear_function() (line_fsym = 0) 30933965Sjdp#define set_function(F) (line_fsym = (F), coff_add_linesym (F)) 31033965Sjdp 31133965Sjdp 31233965Sjdpvoid 313218822Sdimcoff_obj_symbol_new_hook (symbolS *symbolP) 31433965Sjdp{ 31560484Sobrien long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type); 316218822Sdim char * s = xmalloc (sz); 31777298Sobrien 31860484Sobrien memset (s, 0, sz); 31960484Sobrien coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s; 32033965Sjdp 32133965Sjdp S_SET_DATA_TYPE (symbolP, T_NULL); 32233965Sjdp S_SET_STORAGE_CLASS (symbolP, 0); 32333965Sjdp S_SET_NUMBER_AUXILIARY (symbolP, 0); 32433965Sjdp 32533965Sjdp if (S_IS_STRING (symbolP)) 32633965Sjdp SF_SET_STRING (symbolP); 32777298Sobrien 32860484Sobrien if (S_IS_LOCAL (symbolP)) 32933965Sjdp SF_SET_LOCAL (symbolP); 33033965Sjdp} 33133965Sjdp 332218822Sdimvoid 333218822Sdimcoff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP) 334218822Sdim{ 335218822Sdim long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type); 336218822Sdim combined_entry_type * s = xmalloc (sz); 337218822Sdim 338218822Sdim memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native, sz); 339218822Sdim coffsymbol (symbol_get_bfdsym (newsymP))->native = s; 340218822Sdim 341218822Sdim SF_SET (newsymP, SF_GET (orgsymP)); 342218822Sdim} 343218822Sdim 34433965Sjdp 345218822Sdim/* Handle .ln directives. */ 34633965Sjdp 34733965Sjdpstatic symbolS *current_lineno_sym; 34833965Sjdpstatic struct line_no *line_nos; 349218822Sdim/* FIXME: Blindly assume all .ln directives will be in the .text section. */ 35033965Sjdpint coff_n_line_nos; 35133965Sjdp 35233965Sjdpstatic void 353218822Sdimadd_lineno (fragS * frag, addressT offset, int num) 35433965Sjdp{ 355218822Sdim struct line_no * new_line = xmalloc (sizeof (* new_line)); 356218822Sdim 35733965Sjdp if (!current_lineno_sym) 358218822Sdim abort (); 35978828Sobrien 36078828Sobrien#ifndef OBJ_XCOFF 361218822Sdim /* The native aix assembler accepts negative line number. */ 36278828Sobrien 36377298Sobrien if (num <= 0) 36460484Sobrien { 36560484Sobrien /* Zero is used as an end marker in the file. */ 36660484Sobrien as_warn (_("Line numbers must be positive integers\n")); 36760484Sobrien num = 1; 36860484Sobrien } 36978828Sobrien#endif /* OBJ_XCOFF */ 37033965Sjdp new_line->next = line_nos; 37133965Sjdp new_line->frag = frag; 37233965Sjdp new_line->l.line_number = num; 37333965Sjdp new_line->l.u.offset = offset; 37433965Sjdp line_nos = new_line; 37533965Sjdp coff_n_line_nos++; 37633965Sjdp} 37733965Sjdp 37833965Sjdpvoid 379218822Sdimcoff_add_linesym (symbolS *sym) 38033965Sjdp{ 38133965Sjdp if (line_nos) 38233965Sjdp { 38360484Sobrien coffsymbol (symbol_get_bfdsym (current_lineno_sym))->lineno = 38460484Sobrien (alent *) line_nos; 38533965Sjdp coff_n_line_nos++; 38633965Sjdp line_nos = 0; 38733965Sjdp } 38833965Sjdp current_lineno_sym = sym; 38933965Sjdp} 39033965Sjdp 39133965Sjdpstatic void 392218822Sdimobj_coff_ln (int appline) 39333965Sjdp{ 39433965Sjdp int l; 39533965Sjdp 39633965Sjdp if (! appline && def_symbol_in_progress != NULL) 39733965Sjdp { 39860484Sobrien as_warn (_(".ln pseudo-op inside .def/.endef: ignored.")); 39933965Sjdp demand_empty_rest_of_line (); 40033965Sjdp return; 40133965Sjdp } 40233965Sjdp 40333965Sjdp l = get_absolute_expression (); 40433965Sjdp 40589857Sobrien /* If there is no lineno symbol, treat a .ln 40689857Sobrien directive as if it were a .appline directive. */ 40789857Sobrien if (appline || current_lineno_sym == NULL) 40833965Sjdp new_logical_line ((char *) NULL, l - 1); 40989857Sobrien else 41089857Sobrien add_lineno (frag_now, frag_now_fix (), l); 41133965Sjdp 41233965Sjdp#ifndef NO_LISTING 41333965Sjdp { 41433965Sjdp extern int listing; 41533965Sjdp 41633965Sjdp if (listing) 41733965Sjdp { 41833965Sjdp if (! appline) 41933965Sjdp l += coff_line_base - 1; 42033965Sjdp listing_source_line (l); 42133965Sjdp } 42233965Sjdp } 42333965Sjdp#endif 42433965Sjdp 42533965Sjdp demand_empty_rest_of_line (); 42633965Sjdp} 42733965Sjdp 42860484Sobrien/* .loc is essentially the same as .ln; parse it for assembler 42960484Sobrien compatibility. */ 43060484Sobrien 43160484Sobrienstatic void 432218822Sdimobj_coff_loc (int ignore ATTRIBUTE_UNUSED) 43360484Sobrien{ 43460484Sobrien int lineno; 43560484Sobrien 43660484Sobrien /* FIXME: Why do we need this check? We need it for ECOFF, but why 43760484Sobrien do we need it for COFF? */ 43860484Sobrien if (now_seg != text_section) 43960484Sobrien { 44060484Sobrien as_warn (_(".loc outside of .text")); 44160484Sobrien demand_empty_rest_of_line (); 44260484Sobrien return; 44360484Sobrien } 44460484Sobrien 44560484Sobrien if (def_symbol_in_progress != NULL) 44660484Sobrien { 44760484Sobrien as_warn (_(".loc pseudo-op inside .def/.endef: ignored.")); 44860484Sobrien demand_empty_rest_of_line (); 44960484Sobrien return; 45060484Sobrien } 45160484Sobrien 45260484Sobrien /* Skip the file number. */ 45360484Sobrien SKIP_WHITESPACE (); 45460484Sobrien get_absolute_expression (); 45560484Sobrien SKIP_WHITESPACE (); 45660484Sobrien 45760484Sobrien lineno = get_absolute_expression (); 45860484Sobrien 45960484Sobrien#ifndef NO_LISTING 46060484Sobrien { 46160484Sobrien extern int listing; 46260484Sobrien 46360484Sobrien if (listing) 46460484Sobrien { 465104834Sobrien lineno += coff_line_base - 1; 46660484Sobrien listing_source_line (lineno); 46760484Sobrien } 46860484Sobrien } 46960484Sobrien#endif 47060484Sobrien 47160484Sobrien demand_empty_rest_of_line (); 47260484Sobrien 47360484Sobrien add_lineno (frag_now, frag_now_fix (), lineno); 47460484Sobrien} 47560484Sobrien 47660484Sobrien/* Handle the .ident pseudo-op. */ 47760484Sobrien 47860484Sobrienstatic void 479218822Sdimobj_coff_ident (int ignore ATTRIBUTE_UNUSED) 48060484Sobrien{ 48160484Sobrien segT current_seg = now_seg; 48260484Sobrien subsegT current_subseg = now_subseg; 48360484Sobrien 48460484Sobrien#ifdef TE_PE 48560484Sobrien { 48660484Sobrien segT sec; 48760484Sobrien 48860484Sobrien /* We could put it in .comment, but that creates an extra section 48960484Sobrien that shouldn't be loaded into memory, which requires linker 49060484Sobrien changes... For now, until proven otherwise, use .rdata. */ 49160484Sobrien sec = subseg_new (".rdata$zzz", 0); 49260484Sobrien bfd_set_section_flags (stdoutput, sec, 49360484Sobrien ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA) 49460484Sobrien & bfd_applicable_section_flags (stdoutput))); 49560484Sobrien } 49660484Sobrien#else 49760484Sobrien subseg_new (".comment", 0); 49860484Sobrien#endif 49960484Sobrien 50060484Sobrien stringer (1); 50160484Sobrien subseg_set (current_seg, current_subseg); 50260484Sobrien} 50360484Sobrien 504218822Sdim/* Handle .def directives. 50533965Sjdp 506218822Sdim One might ask : why can't we symbol_new if the symbol does not 507218822Sdim already exist and fill it with debug information. Because of 508218822Sdim the C_EFCN special symbol. It would clobber the value of the 509218822Sdim function symbol before we have a chance to notice that it is 510218822Sdim a C_EFCN. And a second reason is that the code is more clear this 511218822Sdim way. (at least I think it is :-). */ 512218822Sdim 51333965Sjdp#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') 51433965Sjdp#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ 515218822Sdim *input_line_pointer == '\t') \ 516218822Sdim input_line_pointer++; 51733965Sjdp 51833965Sjdpstatic void 519218822Sdimobj_coff_def (int what ATTRIBUTE_UNUSED) 52033965Sjdp{ 521218822Sdim char name_end; /* Char after the end of name. */ 522218822Sdim char *symbol_name; /* Name of the debug symbol. */ 523218822Sdim char *symbol_name_copy; /* Temporary copy of the name. */ 52433965Sjdp unsigned int symbol_name_length; 52533965Sjdp 52633965Sjdp if (def_symbol_in_progress != NULL) 52733965Sjdp { 52860484Sobrien as_warn (_(".def pseudo-op used inside of .def/.endef: ignored.")); 52933965Sjdp demand_empty_rest_of_line (); 53033965Sjdp return; 531218822Sdim } 53233965Sjdp 53333965Sjdp SKIP_WHITESPACES (); 53433965Sjdp 53533965Sjdp symbol_name = input_line_pointer; 53633965Sjdp name_end = get_symbol_end (); 53733965Sjdp symbol_name_length = strlen (symbol_name); 53833965Sjdp symbol_name_copy = xmalloc (symbol_name_length + 1); 53933965Sjdp strcpy (symbol_name_copy, symbol_name); 54033965Sjdp#ifdef tc_canonicalize_symbol_name 54133965Sjdp symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy); 54233965Sjdp#endif 54333965Sjdp 544218822Sdim /* Initialize the new symbol. */ 54533965Sjdp def_symbol_in_progress = symbol_make (symbol_name_copy); 54660484Sobrien symbol_set_frag (def_symbol_in_progress, &zero_address_frag); 54733965Sjdp S_SET_VALUE (def_symbol_in_progress, 0); 54833965Sjdp 54933965Sjdp if (S_IS_STRING (def_symbol_in_progress)) 55033965Sjdp SF_SET_STRING (def_symbol_in_progress); 55133965Sjdp 55233965Sjdp *input_line_pointer = name_end; 55333965Sjdp 55433965Sjdp demand_empty_rest_of_line (); 55533965Sjdp} 55633965Sjdp 55733965Sjdpunsigned int dim_index; 55833965Sjdp 55933965Sjdpstatic void 560218822Sdimobj_coff_endef (int ignore ATTRIBUTE_UNUSED) 56133965Sjdp{ 56277298Sobrien symbolS *symbolP = NULL; 56360484Sobrien 56433965Sjdp dim_index = 0; 56533965Sjdp if (def_symbol_in_progress == NULL) 56633965Sjdp { 56760484Sobrien as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored.")); 56833965Sjdp demand_empty_rest_of_line (); 56933965Sjdp return; 570218822Sdim } 57133965Sjdp 57277298Sobrien /* Set the section number according to storage class. */ 57333965Sjdp switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) 57433965Sjdp { 57533965Sjdp case C_STRTAG: 57633965Sjdp case C_ENTAG: 57733965Sjdp case C_UNTAG: 57833965Sjdp SF_SET_TAG (def_symbol_in_progress); 579218822Sdim /* Fall through. */ 58033965Sjdp case C_FILE: 58133965Sjdp case C_TPDEF: 58233965Sjdp SF_SET_DEBUG (def_symbol_in_progress); 58333965Sjdp S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ()); 58433965Sjdp break; 58533965Sjdp 58633965Sjdp case C_EFCN: 58777298Sobrien SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ 588218822Sdim /* Fall through. */ 58933965Sjdp case C_BLOCK: 590218822Sdim SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing. */ 591218822Sdim /* Fall through. */ 59233965Sjdp case C_FCN: 59333965Sjdp { 594104834Sobrien const char *name; 595218822Sdim 59633965Sjdp S_SET_SEGMENT (def_symbol_in_progress, text_section); 59733965Sjdp 59860484Sobrien name = S_GET_NAME (def_symbol_in_progress); 59960484Sobrien if (name[0] == '.' && name[2] == 'f' && name[3] == '\0') 600104834Sobrien { 60160484Sobrien switch (name[1]) 60260484Sobrien { 60377298Sobrien case 'b': 60460484Sobrien /* .bf */ 60560484Sobrien if (! in_function ()) 60660484Sobrien as_warn (_("`%s' symbol without preceding function"), name); 60760484Sobrien /* Will need relocating. */ 60860484Sobrien SF_SET_PROCESS (def_symbol_in_progress); 60960484Sobrien clear_function (); 61060484Sobrien break; 61160484Sobrien#ifdef TE_PE 61277298Sobrien case 'e': 61360484Sobrien /* .ef */ 61460484Sobrien /* The MS compilers output the actual endline, not the 61560484Sobrien function-relative one... we want to match without 61660484Sobrien changing the assembler input. */ 61777298Sobrien SA_SET_SYM_LNNO (def_symbol_in_progress, 61860484Sobrien (SA_GET_SYM_LNNO (def_symbol_in_progress) 61960484Sobrien + coff_line_base)); 62060484Sobrien break; 62160484Sobrien#endif 62260484Sobrien } 62333965Sjdp } 62433965Sjdp } 62533965Sjdp break; 62633965Sjdp 62733965Sjdp#ifdef C_AUTOARG 62833965Sjdp case C_AUTOARG: 62933965Sjdp#endif /* C_AUTOARG */ 63033965Sjdp case C_AUTO: 63133965Sjdp case C_REG: 63233965Sjdp case C_ARG: 63333965Sjdp case C_REGPARM: 63433965Sjdp case C_FIELD: 63577298Sobrien 63677298Sobrien /* According to the COFF documentation: 63777298Sobrien 63877298Sobrien http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html 63977298Sobrien 64077298Sobrien A special section number (-2) marks symbolic debugging symbols, 64177298Sobrien including structure/union/enumeration tag names, typedefs, and 64277298Sobrien the name of the file. A section number of -1 indicates that the 64377298Sobrien symbol has a value but is not relocatable. Examples of 64477298Sobrien absolute-valued symbols include automatic and register variables, 64577298Sobrien function arguments, and .eos symbols. 64677298Sobrien 64777298Sobrien But from Ian Lance Taylor: 64877298Sobrien 64977298Sobrien http://sources.redhat.com/ml/binutils/2000-08/msg00202.html 65077298Sobrien 65177298Sobrien the actual tools all marked them as section -1. So the GNU COFF 65277298Sobrien assembler follows historical COFF assemblers. 65377298Sobrien 65477298Sobrien However, it causes problems for djgpp 65577298Sobrien 65677298Sobrien http://sources.redhat.com/ml/binutils/2000-08/msg00210.html 65777298Sobrien 65877298Sobrien By defining STRICTCOFF, a COFF port can make the assembler to 65977298Sobrien follow the documented behavior. */ 66077298Sobrien#ifdef STRICTCOFF 66177298Sobrien case C_MOS: 66277298Sobrien case C_MOE: 66377298Sobrien case C_MOU: 66477298Sobrien case C_EOS: 66577298Sobrien#endif 66633965Sjdp SF_SET_DEBUG (def_symbol_in_progress); 66733965Sjdp S_SET_SEGMENT (def_symbol_in_progress, absolute_section); 66833965Sjdp break; 66933965Sjdp 67077298Sobrien#ifndef STRICTCOFF 67133965Sjdp case C_MOS: 67233965Sjdp case C_MOE: 67333965Sjdp case C_MOU: 67433965Sjdp case C_EOS: 67533965Sjdp S_SET_SEGMENT (def_symbol_in_progress, absolute_section); 67633965Sjdp break; 67777298Sobrien#endif 67833965Sjdp 67933965Sjdp case C_EXT: 68060484Sobrien case C_WEAKEXT: 68160484Sobrien#ifdef TE_PE 68260484Sobrien case C_NT_WEAK: 68360484Sobrien#endif 68433965Sjdp case C_STAT: 68533965Sjdp case C_LABEL: 686218822Sdim /* Valid but set somewhere else (s_comm, s_lcomm, colon). */ 68733965Sjdp break; 68833965Sjdp 68960484Sobrien default: 69033965Sjdp case C_USTATIC: 69133965Sjdp case C_EXTDEF: 69233965Sjdp case C_ULABEL: 69360484Sobrien as_warn (_("unexpected storage class %d"), 69433965Sjdp S_GET_STORAGE_CLASS (def_symbol_in_progress)); 69533965Sjdp break; 696218822Sdim } 69733965Sjdp 69833965Sjdp /* Now that we have built a debug symbol, try to find if we should 69933965Sjdp merge with an existing symbol or not. If a symbol is C_EFCN or 70060484Sobrien absolute_section or untagged SEG_DEBUG it never merges. We also 70160484Sobrien don't merge labels, which are in a different namespace, nor 70260484Sobrien symbols which have not yet been defined since they are typically 70360484Sobrien unique, nor do we merge tags with non-tags. */ 70433965Sjdp 70533965Sjdp /* Two cases for functions. Either debug followed by definition or 70633965Sjdp definition followed by debug. For definition first, we will 70733965Sjdp merge the debug symbol into the definition. For debug first, the 70833965Sjdp lineno entry MUST point to the definition function or else it 70933965Sjdp will point off into space when obj_crawl_symbol_chain() merges 71033965Sjdp the debug symbol into the real symbol. Therefor, let's presume 71177298Sobrien the debug symbol is a real function reference. */ 71233965Sjdp 71333965Sjdp /* FIXME-SOON If for some reason the definition label/symbol is 71433965Sjdp never seen, this will probably leave an undefined symbol at link 71577298Sobrien time. */ 71633965Sjdp 71733965Sjdp if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN 71860484Sobrien || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL 719218822Sdim || (streq (bfd_get_section_name (stdoutput, 720218822Sdim S_GET_SEGMENT (def_symbol_in_progress)), 721218822Sdim "*DEBUG*") 72233965Sjdp && !SF_GET_TAG (def_symbol_in_progress)) 72333965Sjdp || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section 72460484Sobrien || ! symbol_constant_p (def_symbol_in_progress) 725218822Sdim || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL 72660484Sobrien || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)) 72733965Sjdp { 72860484Sobrien /* If it already is at the end of the symbol list, do nothing */ 72933965Sjdp if (def_symbol_in_progress != symbol_lastP) 730104834Sobrien { 73160484Sobrien symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); 73260484Sobrien symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, 73360484Sobrien &symbol_lastP); 734104834Sobrien } 73533965Sjdp } 73633965Sjdp else 73733965Sjdp { 73833965Sjdp /* This symbol already exists, merge the newly created symbol 73933965Sjdp into the old one. This is not mandatory. The linker can 74033965Sjdp handle duplicate symbols correctly. But I guess that it save 74133965Sjdp a *lot* of space if the assembly file defines a lot of 742218822Sdim symbols. [loic] */ 74333965Sjdp 74433965Sjdp /* The debug entry (def_symbol_in_progress) is merged into the 74577298Sobrien previous definition. */ 74633965Sjdp 74733965Sjdp c_symbol_merge (def_symbol_in_progress, symbolP); 74833965Sjdp symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); 74933965Sjdp 75033965Sjdp def_symbol_in_progress = symbolP; 75133965Sjdp 75233965Sjdp if (SF_GET_FUNCTION (def_symbol_in_progress) 75333965Sjdp || SF_GET_TAG (def_symbol_in_progress) 75433965Sjdp || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT) 75533965Sjdp { 75633965Sjdp /* For functions, and tags, and static symbols, the symbol 75733965Sjdp *must* be where the debug symbol appears. Move the 75877298Sobrien existing symbol to the current place. */ 759218822Sdim /* If it already is at the end of the symbol list, do nothing. */ 76033965Sjdp if (def_symbol_in_progress != symbol_lastP) 76133965Sjdp { 76233965Sjdp symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); 76333965Sjdp symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); 76433965Sjdp } 76533965Sjdp } 76633965Sjdp } 76733965Sjdp 76833965Sjdp if (SF_GET_TAG (def_symbol_in_progress)) 76933965Sjdp { 77033965Sjdp symbolS *oldtag; 77133965Sjdp 772218822Sdim oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress)); 77333965Sjdp if (oldtag == NULL || ! SF_GET_TAG (oldtag)) 77433965Sjdp tag_insert (S_GET_NAME (def_symbol_in_progress), 77533965Sjdp def_symbol_in_progress); 77633965Sjdp } 77733965Sjdp 77833965Sjdp if (SF_GET_FUNCTION (def_symbol_in_progress)) 77933965Sjdp { 78033965Sjdp know (sizeof (def_symbol_in_progress) <= sizeof (long)); 78133965Sjdp set_function (def_symbol_in_progress); 78233965Sjdp SF_SET_PROCESS (def_symbol_in_progress); 78333965Sjdp 78433965Sjdp if (symbolP == NULL) 785218822Sdim /* That is, if this is the first time we've seen the 786218822Sdim function. */ 787218822Sdim symbol_table_insert (def_symbol_in_progress); 78833965Sjdp 789218822Sdim } 790218822Sdim 79133965Sjdp def_symbol_in_progress = NULL; 79233965Sjdp demand_empty_rest_of_line (); 79333965Sjdp} 79433965Sjdp 79533965Sjdpstatic void 796218822Sdimobj_coff_dim (int ignore ATTRIBUTE_UNUSED) 79733965Sjdp{ 79833965Sjdp int dim_index; 79933965Sjdp 80033965Sjdp if (def_symbol_in_progress == NULL) 80133965Sjdp { 80260484Sobrien as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored.")); 80333965Sjdp demand_empty_rest_of_line (); 80433965Sjdp return; 805218822Sdim } 80633965Sjdp 80733965Sjdp S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); 80833965Sjdp 80933965Sjdp for (dim_index = 0; dim_index < DIMNUM; dim_index++) 81033965Sjdp { 81133965Sjdp SKIP_WHITESPACES (); 81233965Sjdp SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, 81333965Sjdp get_absolute_expression ()); 81433965Sjdp 81533965Sjdp switch (*input_line_pointer) 81633965Sjdp { 81733965Sjdp case ',': 81833965Sjdp input_line_pointer++; 81933965Sjdp break; 82033965Sjdp 82133965Sjdp default: 82260484Sobrien as_warn (_("badly formed .dim directive ignored")); 823218822Sdim /* Fall through. */ 82433965Sjdp case '\n': 82533965Sjdp case ';': 82633965Sjdp dim_index = DIMNUM; 82733965Sjdp break; 82833965Sjdp } 82933965Sjdp } 83033965Sjdp 83133965Sjdp demand_empty_rest_of_line (); 83233965Sjdp} 83333965Sjdp 83433965Sjdpstatic void 835218822Sdimobj_coff_line (int ignore ATTRIBUTE_UNUSED) 83633965Sjdp{ 83733965Sjdp int this_base; 83833965Sjdp 83933965Sjdp if (def_symbol_in_progress == NULL) 84033965Sjdp { 84133965Sjdp /* Probably stabs-style line? */ 84233965Sjdp obj_coff_ln (0); 84333965Sjdp return; 84433965Sjdp } 84533965Sjdp 84633965Sjdp this_base = get_absolute_expression (); 847218822Sdim if (streq (".bf", S_GET_NAME (def_symbol_in_progress))) 84833965Sjdp coff_line_base = this_base; 84933965Sjdp 85033965Sjdp S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); 85160484Sobrien SA_SET_SYM_LNNO (def_symbol_in_progress, this_base); 85233965Sjdp 85333965Sjdp demand_empty_rest_of_line (); 85433965Sjdp 85533965Sjdp#ifndef NO_LISTING 856218822Sdim if (streq (".bf", S_GET_NAME (def_symbol_in_progress))) 85733965Sjdp { 85833965Sjdp extern int listing; 85933965Sjdp 86033965Sjdp if (listing) 86160484Sobrien listing_source_line ((unsigned int) this_base); 86233965Sjdp } 86333965Sjdp#endif 86433965Sjdp} 86533965Sjdp 86633965Sjdpstatic void 867218822Sdimobj_coff_size (int ignore ATTRIBUTE_UNUSED) 86833965Sjdp{ 86933965Sjdp if (def_symbol_in_progress == NULL) 87033965Sjdp { 87160484Sobrien as_warn (_(".size pseudo-op used outside of .def/.endef ignored.")); 87233965Sjdp demand_empty_rest_of_line (); 87333965Sjdp return; 874218822Sdim } 87533965Sjdp 87633965Sjdp S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); 87733965Sjdp SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); 87833965Sjdp demand_empty_rest_of_line (); 87933965Sjdp} 88033965Sjdp 88133965Sjdpstatic void 882218822Sdimobj_coff_scl (int ignore ATTRIBUTE_UNUSED) 88333965Sjdp{ 88433965Sjdp if (def_symbol_in_progress == NULL) 88533965Sjdp { 88660484Sobrien as_warn (_(".scl pseudo-op used outside of .def/.endef ignored.")); 88733965Sjdp demand_empty_rest_of_line (); 88833965Sjdp return; 889218822Sdim } 89033965Sjdp 89133965Sjdp S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); 89233965Sjdp demand_empty_rest_of_line (); 89333965Sjdp} 89433965Sjdp 89533965Sjdpstatic void 896218822Sdimobj_coff_tag (int ignore ATTRIBUTE_UNUSED) 89733965Sjdp{ 89833965Sjdp char *symbol_name; 89933965Sjdp char name_end; 90033965Sjdp 90133965Sjdp if (def_symbol_in_progress == NULL) 90233965Sjdp { 90360484Sobrien as_warn (_(".tag pseudo-op used outside of .def/.endef ignored.")); 90433965Sjdp demand_empty_rest_of_line (); 90533965Sjdp return; 90633965Sjdp } 90733965Sjdp 90833965Sjdp S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); 90933965Sjdp symbol_name = input_line_pointer; 91033965Sjdp name_end = get_symbol_end (); 91133965Sjdp 91233965Sjdp#ifdef tc_canonicalize_symbol_name 91333965Sjdp symbol_name = tc_canonicalize_symbol_name (symbol_name); 91433965Sjdp#endif 91533965Sjdp 91633965Sjdp /* Assume that the symbol referred to by .tag is always defined. 91777298Sobrien This was a bad assumption. I've added find_or_make. xoxorich. */ 91833965Sjdp SA_SET_SYM_TAGNDX (def_symbol_in_progress, 91933965Sjdp tag_find_or_make (symbol_name)); 92033965Sjdp if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) 921218822Sdim as_warn (_("tag not found for .tag %s"), symbol_name); 92233965Sjdp 92333965Sjdp SF_SET_TAGGED (def_symbol_in_progress); 92433965Sjdp *input_line_pointer = name_end; 92533965Sjdp 92633965Sjdp demand_empty_rest_of_line (); 92733965Sjdp} 92833965Sjdp 92933965Sjdpstatic void 930218822Sdimobj_coff_type (int ignore ATTRIBUTE_UNUSED) 93133965Sjdp{ 93233965Sjdp if (def_symbol_in_progress == NULL) 93333965Sjdp { 93460484Sobrien as_warn (_(".type pseudo-op used outside of .def/.endef ignored.")); 93533965Sjdp demand_empty_rest_of_line (); 93633965Sjdp return; 937218822Sdim } 93833965Sjdp 93933965Sjdp S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); 94033965Sjdp 94133965Sjdp if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && 94233965Sjdp S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) 943218822Sdim SF_SET_FUNCTION (def_symbol_in_progress); 94433965Sjdp 94533965Sjdp demand_empty_rest_of_line (); 94633965Sjdp} 94733965Sjdp 94833965Sjdpstatic void 949218822Sdimobj_coff_val (int ignore ATTRIBUTE_UNUSED) 95033965Sjdp{ 95133965Sjdp if (def_symbol_in_progress == NULL) 95233965Sjdp { 95360484Sobrien as_warn (_(".val pseudo-op used outside of .def/.endef ignored.")); 95433965Sjdp demand_empty_rest_of_line (); 95533965Sjdp return; 956218822Sdim } 95733965Sjdp 95833965Sjdp if (is_name_beginner (*input_line_pointer)) 95933965Sjdp { 96033965Sjdp char *symbol_name = input_line_pointer; 96133965Sjdp char name_end = get_symbol_end (); 96233965Sjdp 96333965Sjdp#ifdef tc_canonicalize_symbol_name 96433965Sjdp symbol_name = tc_canonicalize_symbol_name (symbol_name); 96533965Sjdp#endif 966218822Sdim if (streq (symbol_name, ".")) 96733965Sjdp { 968218822Sdim /* If the .val is != from the .def (e.g. statics). */ 96960484Sobrien symbol_set_frag (def_symbol_in_progress, frag_now); 97033965Sjdp S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); 97133965Sjdp } 972218822Sdim else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name)) 97333965Sjdp { 97460484Sobrien expressionS exp; 97533965Sjdp 97660484Sobrien exp.X_op = O_symbol; 97760484Sobrien exp.X_add_symbol = symbol_find_or_make (symbol_name); 97860484Sobrien exp.X_op_symbol = NULL; 97960484Sobrien exp.X_add_number = 0; 98060484Sobrien symbol_set_value_expression (def_symbol_in_progress, &exp); 98160484Sobrien 98233965Sjdp /* If the segment is undefined when the forward reference is 98333965Sjdp resolved, then copy the segment id from the forward 98433965Sjdp symbol. */ 98533965Sjdp SF_SET_GET_SEGMENT (def_symbol_in_progress); 98660484Sobrien 98760484Sobrien /* FIXME: gcc can generate address expressions here in 98860484Sobrien unusual cases (search for "obscure" in sdbout.c). We 98960484Sobrien just ignore the offset here, thus generating incorrect 99060484Sobrien debugging information. We ignore the rest of the line 99160484Sobrien just below. */ 99233965Sjdp } 99360484Sobrien /* Otherwise, it is the name of a non debug symbol and its value 99477298Sobrien will be calculated later. */ 99533965Sjdp *input_line_pointer = name_end; 99633965Sjdp } 99733965Sjdp else 99833965Sjdp { 99933965Sjdp S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); 1000218822Sdim } 100133965Sjdp 100233965Sjdp demand_empty_rest_of_line (); 100333965Sjdp} 100433965Sjdp 1005218822Sdim#ifdef TE_PE 1006218822Sdim 1007218822Sdim/* Return nonzero if name begins with weak alternate symbol prefix. */ 1008218822Sdim 1009218822Sdimstatic int 1010218822Sdimweak_is_altname (const char * name) 1011218822Sdim{ 1012218822Sdim return strneq (name, weak_altprefix, sizeof (weak_altprefix) - 1); 1013218822Sdim} 1014218822Sdim 1015218822Sdim/* Return the name of the alternate symbol 1016218822Sdim name corresponding to a weak symbol's name. */ 1017218822Sdim 1018218822Sdimstatic const char * 1019218822Sdimweak_name2altname (const char * name) 1020218822Sdim{ 1021218822Sdim char *alt_name; 1022218822Sdim 1023218822Sdim alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name)); 1024218822Sdim strcpy (alt_name, weak_altprefix); 1025218822Sdim return strcat (alt_name, name); 1026218822Sdim} 1027218822Sdim 1028218822Sdim/* Return the name of the weak symbol corresponding to an 1029218822Sdim alternate symbol. */ 1030218822Sdim 1031218822Sdimstatic const char * 1032218822Sdimweak_altname2name (const char * name) 1033218822Sdim{ 1034218822Sdim char * weak_name; 1035218822Sdim char * dot; 1036218822Sdim 1037218822Sdim assert (weak_is_altname (name)); 1038218822Sdim 1039218822Sdim weak_name = xstrdup (name + 6); 1040218822Sdim if ((dot = strchr (weak_name, '.'))) 1041218822Sdim *dot = 0; 1042218822Sdim return weak_name; 1043218822Sdim} 1044218822Sdim 1045218822Sdim/* Make a weak symbol name unique by 1046218822Sdim appending the name of an external symbol. */ 1047218822Sdim 1048218822Sdimstatic const char * 1049218822Sdimweak_uniquify (const char * name) 1050218822Sdim{ 1051218822Sdim char *ret; 1052218822Sdim const char * unique = ""; 1053218822Sdim 1054218822Sdim#ifdef USE_UNIQUE 1055218822Sdim if (an_external_name != NULL) 1056218822Sdim unique = an_external_name; 1057218822Sdim#endif 1058218822Sdim assert (weak_is_altname (name)); 1059218822Sdim 1060218822Sdim if (strchr (name + sizeof (weak_altprefix), '.')) 1061218822Sdim return name; 1062218822Sdim 1063218822Sdim ret = xmalloc (strlen (name) + strlen (unique) + 2); 1064218822Sdim strcpy (ret, name); 1065218822Sdim strcat (ret, "."); 1066218822Sdim strcat (ret, unique); 1067218822Sdim return ret; 1068218822Sdim} 1069218822Sdim 107033965Sjdpvoid 1071218822Sdimpecoff_obj_set_weak_hook (symbolS *symbolP) 107233965Sjdp{ 1073218822Sdim symbolS *alternateP; 1074218822Sdim 1075218822Sdim /* See _Microsoft Portable Executable and Common Object 1076218822Sdim File Format Specification_, section 5.5.3. 1077218822Sdim Create a symbol representing the alternate value. 1078218822Sdim coff_frob_symbol will set the value of this symbol from 1079218822Sdim the value of the weak symbol itself. */ 1080218822Sdim S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK); 1081218822Sdim S_SET_NUMBER_AUXILIARY (symbolP, 1); 1082218822Sdim SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); 1083218822Sdim 1084218822Sdim alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP))); 1085218822Sdim S_SET_EXTERNAL (alternateP); 1086218822Sdim S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK); 1087218822Sdim 1088218822Sdim SA_SET_SYM_TAGNDX (symbolP, alternateP); 1089218822Sdim} 1090218822Sdim 1091218822Sdimvoid 1092218822Sdimpecoff_obj_clear_weak_hook (symbolS *symbolP) 1093218822Sdim{ 1094218822Sdim symbolS *alternateP; 1095218822Sdim 1096218822Sdim S_SET_STORAGE_CLASS (symbolP, 0); 1097218822Sdim SA_SET_SYM_FSIZE (symbolP, 0); 1098218822Sdim 1099218822Sdim alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP))); 1100218822Sdim S_CLEAR_EXTERNAL (alternateP); 1101218822Sdim} 1102218822Sdim 1103218822Sdim#endif /* TE_PE */ 1104218822Sdim 1105218822Sdim/* Handle .weak. This is a GNU extension in formats other than PE. */ 1106218822Sdim 1107218822Sdimstatic void 1108218822Sdimobj_coff_weak (int ignore ATTRIBUTE_UNUSED) 1109218822Sdim{ 1110218822Sdim char *name; 1111218822Sdim int c; 1112218822Sdim symbolS *symbolP; 1113218822Sdim 1114218822Sdim do 1115218822Sdim { 1116218822Sdim name = input_line_pointer; 1117218822Sdim c = get_symbol_end (); 1118218822Sdim if (*name == 0) 1119218822Sdim { 1120218822Sdim as_warn (_("badly formed .weak directive ignored")); 1121218822Sdim ignore_rest_of_line (); 1122218822Sdim return; 1123218822Sdim } 1124218822Sdim c = 0; 1125218822Sdim symbolP = symbol_find_or_make (name); 1126218822Sdim *input_line_pointer = c; 1127218822Sdim SKIP_WHITESPACE (); 1128218822Sdim S_SET_WEAK (symbolP); 1129218822Sdim 1130218822Sdim if (c == ',') 1131218822Sdim { 1132218822Sdim input_line_pointer++; 1133218822Sdim SKIP_WHITESPACE (); 1134218822Sdim if (*input_line_pointer == '\n') 1135218822Sdim c = '\n'; 1136218822Sdim } 1137218822Sdim 1138218822Sdim } 1139218822Sdim while (c == ','); 1140218822Sdim 1141218822Sdim demand_empty_rest_of_line (); 1142218822Sdim} 1143218822Sdim 1144218822Sdimvoid 1145218822Sdimcoff_obj_read_begin_hook (void) 1146218822Sdim{ 114777298Sobrien /* These had better be the same. Usually 18 bytes. */ 114833965Sjdp know (sizeof (SYMENT) == sizeof (AUXENT)); 114933965Sjdp know (SYMESZ == AUXESZ); 115033965Sjdp tag_init (); 115133965Sjdp} 115233965Sjdp 115333965SjdpsymbolS *coff_last_function; 1154130561Sobrien#ifndef OBJ_XCOFF 115533965Sjdpstatic symbolS *coff_last_bf; 1156130561Sobrien#endif 115733965Sjdp 115833965Sjdpvoid 1159218822Sdimcoff_frob_symbol (symbolS *symp, int *punt) 116033965Sjdp{ 116133965Sjdp static symbolS *last_tagP; 116233965Sjdp static stack *block_stack; 116333965Sjdp static symbolS *set_end; 116433965Sjdp symbolS *next_set_end = NULL; 116533965Sjdp 116633965Sjdp if (symp == &abs_symbol) 116733965Sjdp { 116833965Sjdp *punt = 1; 116933965Sjdp return; 117033965Sjdp } 117133965Sjdp 117233965Sjdp if (current_lineno_sym) 1173218822Sdim coff_add_linesym (NULL); 117433965Sjdp 117533965Sjdp if (!block_stack) 117633965Sjdp block_stack = stack_init (512, sizeof (symbolS*)); 117733965Sjdp 1178218822Sdim#ifdef TE_PE 1179218822Sdim if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK 1180218822Sdim && ! S_IS_WEAK (symp) 1181218822Sdim && weak_is_altname (S_GET_NAME (symp))) 118260484Sobrien { 1183218822Sdim /* This is a weak alternate symbol. All processing of 1184218822Sdim PECOFFweak symbols is done here, through the alternate. */ 1185218822Sdim symbolS *weakp = symbol_find_noref (weak_altname2name 1186218822Sdim (S_GET_NAME (symp)), 1); 1187218822Sdim 1188218822Sdim assert (weakp); 1189218822Sdim assert (S_GET_NUMBER_AUXILIARY (weakp) == 1); 1190218822Sdim 1191218822Sdim if (! S_IS_WEAK (weakp)) 1192218822Sdim { 1193218822Sdim /* The symbol was turned from weak to strong. Discard altname. */ 1194218822Sdim *punt = 1; 1195218822Sdim return; 1196218822Sdim } 1197218822Sdim else if (symbol_equated_p (weakp)) 1198218822Sdim { 1199218822Sdim /* The weak symbol has an alternate specified; symp is unneeded. */ 1200218822Sdim S_SET_STORAGE_CLASS (weakp, C_NT_WEAK); 1201218822Sdim SA_SET_SYM_TAGNDX (weakp, 1202218822Sdim symbol_get_value_expression (weakp)->X_add_symbol); 1203218822Sdim 1204218822Sdim S_CLEAR_EXTERNAL (symp); 1205218822Sdim *punt = 1; 1206218822Sdim return; 1207218822Sdim } 1208218822Sdim else 1209218822Sdim { 1210218822Sdim /* The weak symbol has been assigned an alternate value. 1211218822Sdim Copy this value to symp, and set symp as weakp's alternate. */ 1212218822Sdim if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK) 1213218822Sdim { 1214218822Sdim S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp)); 1215218822Sdim S_SET_STORAGE_CLASS (weakp, C_NT_WEAK); 1216218822Sdim } 1217218822Sdim 1218218822Sdim if (S_IS_DEFINED (weakp)) 1219218822Sdim { 1220218822Sdim /* This is a defined weak symbol. Copy value information 1221218822Sdim from the weak symbol itself to the alternate symbol. */ 1222218822Sdim symbol_set_value_expression (symp, 1223218822Sdim symbol_get_value_expression (weakp)); 1224218822Sdim symbol_set_frag (symp, symbol_get_frag (weakp)); 1225218822Sdim S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp)); 1226218822Sdim } 1227218822Sdim else 1228218822Sdim { 1229218822Sdim /* This is an undefined weak symbol. 1230218822Sdim Define the alternate symbol to zero. */ 1231218822Sdim S_SET_VALUE (symp, 0); 1232218822Sdim S_SET_SEGMENT (symp, absolute_section); 1233218822Sdim } 1234218822Sdim 1235218822Sdim S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp))); 1236218822Sdim S_SET_STORAGE_CLASS (symp, C_EXT); 1237218822Sdim 1238218822Sdim S_SET_VALUE (weakp, 0); 1239218822Sdim S_SET_SEGMENT (weakp, undefined_section); 1240218822Sdim } 124160484Sobrien } 1242218822Sdim#else /* TE_PE */ 1243218822Sdim if (S_IS_WEAK (symp)) 1244218822Sdim S_SET_STORAGE_CLASS (symp, C_WEAKEXT); 1245218822Sdim#endif /* TE_PE */ 124660484Sobrien 124760484Sobrien if (!S_IS_DEFINED (symp) 124860484Sobrien && !S_IS_WEAK (symp) 124960484Sobrien && S_GET_STORAGE_CLASS (symp) != C_STAT) 125033965Sjdp S_SET_STORAGE_CLASS (symp, C_EXT); 125133965Sjdp 125233965Sjdp if (!SF_GET_DEBUG (symp)) 125333965Sjdp { 125489857Sobrien symbolS * real; 125589857Sobrien 125633965Sjdp if (!SF_GET_LOCAL (symp) 125733965Sjdp && !SF_GET_STATICS (symp) 125877298Sobrien && S_GET_STORAGE_CLASS (symp) != C_LABEL 1259218822Sdim && symbol_constant_p (symp) 1260218822Sdim && (real = symbol_find_noref (S_GET_NAME (symp), 1)) 126189857Sobrien && S_GET_STORAGE_CLASS (real) == C_NULL 126233965Sjdp && real != symp) 126333965Sjdp { 126433965Sjdp c_symbol_merge (symp, real); 126533965Sjdp *punt = 1; 126677298Sobrien return; 126733965Sjdp } 126889857Sobrien 126933965Sjdp if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) 127033965Sjdp { 127133965Sjdp assert (S_GET_VALUE (symp) == 0); 1272218822Sdim if (S_IS_WEAKREFD (symp)) 1273218822Sdim *punt = 1; 1274218822Sdim else 1275218822Sdim S_SET_EXTERNAL (symp); 127633965Sjdp } 127733965Sjdp else if (S_GET_STORAGE_CLASS (symp) == C_NULL) 127833965Sjdp { 127933965Sjdp if (S_GET_SEGMENT (symp) == text_section 128033965Sjdp && symp != seg_info (text_section)->sym) 128133965Sjdp S_SET_STORAGE_CLASS (symp, C_LABEL); 128233965Sjdp else 128333965Sjdp S_SET_STORAGE_CLASS (symp, C_STAT); 128433965Sjdp } 128589857Sobrien 128633965Sjdp if (SF_GET_PROCESS (symp)) 128733965Sjdp { 128833965Sjdp if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) 128933965Sjdp { 1290218822Sdim if (streq (S_GET_NAME (symp), ".bb")) 129133965Sjdp stack_push (block_stack, (char *) &symp); 129233965Sjdp else 129333965Sjdp { 129433965Sjdp symbolS *begin; 129589857Sobrien 129633965Sjdp begin = *(symbolS **) stack_pop (block_stack); 129733965Sjdp if (begin == 0) 129860484Sobrien as_warn (_("mismatched .eb")); 129933965Sjdp else 130033965Sjdp next_set_end = begin; 130133965Sjdp } 130233965Sjdp } 130389857Sobrien 130433965Sjdp if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) 130533965Sjdp { 130633965Sjdp union internal_auxent *auxp; 130789857Sobrien 130833965Sjdp coff_last_function = symp; 130933965Sjdp if (S_GET_NUMBER_AUXILIARY (symp) < 1) 131033965Sjdp S_SET_NUMBER_AUXILIARY (symp, 1); 131160484Sobrien auxp = SYM_AUXENT (symp); 131233965Sjdp memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, 131333965Sjdp sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); 131433965Sjdp } 131589857Sobrien 131633965Sjdp if (S_GET_STORAGE_CLASS (symp) == C_EFCN) 131733965Sjdp { 131833965Sjdp if (coff_last_function == 0) 1319218822Sdim as_fatal (_("C_EFCN symbol for %s out of scope"), 1320218822Sdim S_GET_NAME (symp)); 132133965Sjdp SA_SET_SYM_FSIZE (coff_last_function, 132233965Sjdp (long) (S_GET_VALUE (symp) 132333965Sjdp - S_GET_VALUE (coff_last_function))); 132433965Sjdp next_set_end = coff_last_function; 132533965Sjdp coff_last_function = 0; 132633965Sjdp } 132733965Sjdp } 132889857Sobrien 132933965Sjdp if (S_IS_EXTERNAL (symp)) 133033965Sjdp S_SET_STORAGE_CLASS (symp, C_EXT); 133133965Sjdp else if (SF_GET_LOCAL (symp)) 133233965Sjdp *punt = 1; 133333965Sjdp 133433965Sjdp if (SF_GET_FUNCTION (symp)) 133560484Sobrien symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION; 133633965Sjdp } 133733965Sjdp 133860484Sobrien /* Double check weak symbols. */ 133960484Sobrien if (S_IS_WEAK (symp) && S_IS_COMMON (symp)) 134060484Sobrien as_bad (_("Symbol `%s' can not be both weak and common"), 134160484Sobrien S_GET_NAME (symp)); 134260484Sobrien 134333965Sjdp if (SF_GET_TAG (symp)) 134433965Sjdp last_tagP = symp; 134533965Sjdp else if (S_GET_STORAGE_CLASS (symp) == C_EOS) 134633965Sjdp next_set_end = last_tagP; 134733965Sjdp 134833965Sjdp#ifdef OBJ_XCOFF 134933965Sjdp /* This is pretty horrible, but we have to set *punt correctly in 135033965Sjdp order to call SA_SET_SYM_ENDNDX correctly. */ 135160484Sobrien if (! symbol_used_in_reloc_p (symp) 135260484Sobrien && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0 1353218822Sdim || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp)) 135460484Sobrien && ! symbol_get_tc (symp)->output 135533965Sjdp && S_GET_STORAGE_CLASS (symp) != C_FILE))) 135633965Sjdp *punt = 1; 135733965Sjdp#endif 135833965Sjdp 135933965Sjdp if (set_end != (symbolS *) NULL 136033965Sjdp && ! *punt 136160484Sobrien && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0 136233965Sjdp || (S_IS_DEFINED (symp) 136333965Sjdp && ! S_IS_COMMON (symp) 136433965Sjdp && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp))))) 136533965Sjdp { 136633965Sjdp SA_SET_SYM_ENDNDX (set_end, symp); 136733965Sjdp set_end = NULL; 136833965Sjdp } 136933965Sjdp 137060484Sobrien if (next_set_end != NULL) 137160484Sobrien { 137260484Sobrien if (set_end != NULL) 137360484Sobrien as_warn ("Warning: internal error: forgetting to set endndx of %s", 137460484Sobrien S_GET_NAME (set_end)); 137560484Sobrien set_end = next_set_end; 137660484Sobrien } 137733965Sjdp 137889857Sobrien#ifndef OBJ_XCOFF 137933965Sjdp if (! *punt 138033965Sjdp && S_GET_STORAGE_CLASS (symp) == C_FCN 1381218822Sdim && streq (S_GET_NAME (symp), ".bf")) 138233965Sjdp { 138333965Sjdp if (coff_last_bf != NULL) 138433965Sjdp SA_SET_SYM_ENDNDX (coff_last_bf, symp); 138533965Sjdp coff_last_bf = symp; 138633965Sjdp } 138789857Sobrien#endif 138860484Sobrien if (coffsymbol (symbol_get_bfdsym (symp))->lineno) 138933965Sjdp { 139033965Sjdp int i; 139133965Sjdp struct line_no *lptr; 139233965Sjdp alent *l; 139333965Sjdp 139460484Sobrien lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; 139533965Sjdp for (i = 0; lptr; lptr = lptr->next) 139633965Sjdp i++; 139760484Sobrien lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; 139833965Sjdp 139933965Sjdp /* We need i entries for line numbers, plus 1 for the first 140033965Sjdp entry which BFD will override, plus 1 for the last zero 140133965Sjdp entry (a marker for BFD). */ 1402218822Sdim l = xmalloc ((i + 2) * sizeof (* l)); 140360484Sobrien coffsymbol (symbol_get_bfdsym (symp))->lineno = l; 140433965Sjdp l[i + 1].line_number = 0; 140533965Sjdp l[i + 1].u.sym = NULL; 140633965Sjdp for (; i > 0; i--) 140733965Sjdp { 140833965Sjdp if (lptr->frag) 140960484Sobrien lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE; 141033965Sjdp l[i] = lptr->l; 141133965Sjdp lptr = lptr->next; 141233965Sjdp } 141333965Sjdp } 141433965Sjdp} 141533965Sjdp 141633965Sjdpvoid 1417218822Sdimcoff_adjust_section_syms (bfd *abfd ATTRIBUTE_UNUSED, 1418218822Sdim asection *sec, 1419218822Sdim void * x ATTRIBUTE_UNUSED) 142033965Sjdp{ 142133965Sjdp symbolS *secsym; 142233965Sjdp segment_info_type *seginfo = seg_info (sec); 142333965Sjdp int nlnno, nrelocs = 0; 142433965Sjdp 142533965Sjdp /* RS/6000 gas creates a .debug section manually in ppc_frob_file in 142633965Sjdp tc-ppc.c. Do not get confused by it. */ 142733965Sjdp if (seginfo == NULL) 142833965Sjdp return; 142933965Sjdp 1430218822Sdim if (streq (sec->name, ".text")) 143133965Sjdp nlnno = coff_n_line_nos; 143233965Sjdp else 143333965Sjdp nlnno = 0; 143433965Sjdp { 143533965Sjdp /* @@ Hope that none of the fixups expand to more than one reloc 143633965Sjdp entry... */ 143733965Sjdp fixS *fixp = seginfo->fix_root; 143833965Sjdp while (fixp) 143933965Sjdp { 144038889Sjdp if (! fixp->fx_done) 144138889Sjdp nrelocs++; 144233965Sjdp fixp = fixp->fx_next; 144333965Sjdp } 144433965Sjdp } 1445218822Sdim if (bfd_get_section_size (sec) == 0 144633965Sjdp && nrelocs == 0 144733965Sjdp && nlnno == 0 144833965Sjdp && sec != text_section 144933965Sjdp && sec != data_section 145033965Sjdp && sec != bss_section) 145133965Sjdp return; 1452218822Sdim 145333965Sjdp secsym = section_symbol (sec); 145460484Sobrien /* This is an estimate; we'll plug in the real value using 145560484Sobrien SET_SECTION_RELOCS later */ 145633965Sjdp SA_SET_SCN_NRELOC (secsym, nrelocs); 145733965Sjdp SA_SET_SCN_NLINNO (secsym, nlnno); 145833965Sjdp} 145933965Sjdp 146033965Sjdpvoid 1461218822Sdimcoff_frob_file_after_relocs (void) 146233965Sjdp{ 1463218822Sdim bfd_map_over_sections (stdoutput, coff_adjust_section_syms, NULL); 146433965Sjdp} 146533965Sjdp 1466104834Sobrien/* Implement the .section pseudo op: 1467104834Sobrien .section name {, "flags"} 1468104834Sobrien ^ ^ 1469104834Sobrien | +--- optional flags: 'b' for bss 1470104834Sobrien | 'i' for info 1471104834Sobrien +-- section name 'l' for lib 1472104834Sobrien 'n' for noload 1473104834Sobrien 'o' for over 1474104834Sobrien 'w' for data 1475104834Sobrien 'd' (apparently m88k for data) 1476104834Sobrien 'x' for text 1477104834Sobrien 'r' for read-only data 1478104834Sobrien 's' for shared data (PE) 1479104834Sobrien But if the argument is not a quoted string, treat it as a 1480104834Sobrien subsegment number. 148133965Sjdp 1482104834Sobrien Note the 'a' flag is silently ignored. This allows the same 1483104834Sobrien .section directive to be parsed in both ELF and COFF formats. */ 1484104834Sobrien 148533965Sjdpvoid 1486218822Sdimobj_coff_section (int ignore ATTRIBUTE_UNUSED) 148733965Sjdp{ 1488218822Sdim /* Strip out the section name. */ 148933965Sjdp char *section_name; 149033965Sjdp char c; 149133965Sjdp char *name; 149233965Sjdp unsigned int exp; 149377298Sobrien flagword flags, oldflags; 149433965Sjdp asection *sec; 149533965Sjdp 149633965Sjdp if (flag_mri) 149733965Sjdp { 149833965Sjdp char type; 149933965Sjdp 150033965Sjdp s_mri_sect (&type); 150133965Sjdp return; 150233965Sjdp } 150333965Sjdp 150433965Sjdp section_name = input_line_pointer; 150533965Sjdp c = get_symbol_end (); 150633965Sjdp 150733965Sjdp name = xmalloc (input_line_pointer - section_name + 1); 150833965Sjdp strcpy (name, section_name); 150933965Sjdp 151033965Sjdp *input_line_pointer = c; 151133965Sjdp 151233965Sjdp SKIP_WHITESPACE (); 151333965Sjdp 151433965Sjdp exp = 0; 151577298Sobrien flags = SEC_NO_FLAGS; 151633965Sjdp 151733965Sjdp if (*input_line_pointer == ',') 151833965Sjdp { 151933965Sjdp ++input_line_pointer; 152033965Sjdp SKIP_WHITESPACE (); 152133965Sjdp if (*input_line_pointer != '"') 152233965Sjdp exp = get_absolute_expression (); 152333965Sjdp else 152433965Sjdp { 1525218822Sdim unsigned char attr; 1526218822Sdim int readonly_removed = 0; 1527218822Sdim int load_removed = 0; 1528218822Sdim 1529218822Sdim while (attr = *++input_line_pointer, 1530218822Sdim attr != '"' 1531218822Sdim && ! is_end_of_line[attr]) 153233965Sjdp { 1533218822Sdim switch (attr) 153433965Sjdp { 1535218822Sdim case 'b': 1536218822Sdim /* Uninitialised data section. */ 1537218822Sdim flags |= SEC_ALLOC; 1538218822Sdim flags &=~ SEC_LOAD; 1539218822Sdim break; 1540130561Sobrien 1541218822Sdim case 'n': 1542218822Sdim /* Section not loaded. */ 1543218822Sdim flags &=~ SEC_LOAD; 1544218822Sdim flags |= SEC_NEVER_LOAD; 1545218822Sdim load_removed = 1; 1546218822Sdim break; 1547130561Sobrien 1548218822Sdim case 's': 1549218822Sdim /* Shared section. */ 1550218822Sdim flags |= SEC_COFF_SHARED; 1551218822Sdim /* Fall through. */ 1552218822Sdim case 'd': 1553218822Sdim /* Data section. */ 1554218822Sdim flags |= SEC_DATA; 1555218822Sdim if (! load_removed) 1556218822Sdim flags |= SEC_LOAD; 1557218822Sdim flags &=~ SEC_READONLY; 1558218822Sdim break; 155933965Sjdp 1560218822Sdim case 'w': 1561218822Sdim /* Writable section. */ 1562218822Sdim flags &=~ SEC_READONLY; 1563218822Sdim readonly_removed = 1; 1564218822Sdim break; 1565218822Sdim 1566218822Sdim case 'a': 1567218822Sdim /* Ignore. Here for compatibility with ELF. */ 1568218822Sdim break; 1569218822Sdim 1570218822Sdim case 'r': /* Read-only section. Implies a data section. */ 1571218822Sdim readonly_removed = 0; 1572218822Sdim /* Fall through. */ 1573218822Sdim case 'x': /* Executable section. */ 1574218822Sdim /* If we are setting the 'x' attribute or if the 'r' 1575218822Sdim attribute is being used to restore the readonly status 1576218822Sdim of a code section (eg "wxr") then set the SEC_CODE flag, 1577218822Sdim otherwise set the SEC_DATA flag. */ 1578218822Sdim flags |= (attr == 'x' || (flags & SEC_CODE) ? SEC_CODE : SEC_DATA); 1579218822Sdim if (! load_removed) 1580218822Sdim flags |= SEC_LOAD; 1581218822Sdim /* Note - the READONLY flag is set here, even for the 'x' 1582218822Sdim attribute in order to be compatible with the MSVC 1583218822Sdim linker. */ 1584218822Sdim if (! readonly_removed) 1585218822Sdim flags |= SEC_READONLY; 1586218822Sdim break; 1587218822Sdim 158833965Sjdp case 'i': /* STYP_INFO */ 158933965Sjdp case 'l': /* STYP_LIB */ 159033965Sjdp case 'o': /* STYP_OVER */ 1591218822Sdim as_warn (_("unsupported section attribute '%c'"), attr); 159233965Sjdp break; 159333965Sjdp 159433965Sjdp default: 1595218822Sdim as_warn (_("unknown section attribute '%c'"), attr); 159633965Sjdp break; 159733965Sjdp } 159833965Sjdp } 1599218822Sdim if (attr == '"') 160033965Sjdp ++input_line_pointer; 160133965Sjdp } 160233965Sjdp } 160333965Sjdp 160433965Sjdp sec = subseg_new (name, (subsegT) exp); 160533965Sjdp 160677298Sobrien oldflags = bfd_get_section_flags (stdoutput, sec); 160777298Sobrien if (oldflags == SEC_NO_FLAGS) 160833965Sjdp { 160977298Sobrien /* Set section flags for a new section just created by subseg_new. 161077298Sobrien Provide a default if no flags were parsed. */ 161177298Sobrien if (flags == SEC_NO_FLAGS) 161277298Sobrien flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES; 161360484Sobrien 161477298Sobrien#ifdef COFF_LONG_SECTION_NAMES 161577298Sobrien /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce 161677298Sobrien sections so adjust_reloc_syms in write.c will correctly handle 161777298Sobrien relocs which refer to non-local symbols in these sections. */ 1618218822Sdim if (strneq (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1)) 1619104834Sobrien flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; 162077298Sobrien#endif 162160484Sobrien 162233965Sjdp if (! bfd_set_section_flags (stdoutput, sec, flags)) 1623104834Sobrien as_warn (_("error setting flags for \"%s\": %s"), 1624104834Sobrien bfd_section_name (stdoutput, sec), 1625104834Sobrien bfd_errmsg (bfd_get_error ())); 162633965Sjdp } 162777298Sobrien else if (flags != SEC_NO_FLAGS) 162877298Sobrien { 1629218822Sdim /* This section's attributes have already been set. Warn if the 163077298Sobrien attributes don't match. */ 163178828Sobrien flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE 1632218822Sdim | SEC_DATA | SEC_COFF_SHARED | SEC_NEVER_LOAD); 163377298Sobrien if ((flags ^ oldflags) & matchflags) 163477298Sobrien as_warn (_("Ignoring changed section attributes for %s"), name); 163577298Sobrien } 163633965Sjdp 163733965Sjdp demand_empty_rest_of_line (); 163833965Sjdp} 163933965Sjdp 164033965Sjdpvoid 1641218822Sdimcoff_adjust_symtab (void) 164233965Sjdp{ 164333965Sjdp if (symbol_rootP == NULL 164433965Sjdp || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) 1645218822Sdim c_dot_file_symbol ("fake", 0); 164633965Sjdp} 164733965Sjdp 164833965Sjdpvoid 1649218822Sdimcoff_frob_section (segT sec) 165033965Sjdp{ 165133965Sjdp segT strsec; 165233965Sjdp char *p; 165333965Sjdp fragS *fragp; 165433965Sjdp bfd_vma size, n_entries, mask; 165560484Sobrien bfd_vma align_power = (bfd_vma)sec->alignment_power + OCTETS_PER_BYTE_POWER; 165633965Sjdp 165733965Sjdp /* The COFF back end in BFD requires that all section sizes be 165860484Sobrien rounded up to multiples of the corresponding section alignments, 165960484Sobrien supposedly because standard COFF has no other way of encoding alignment 166060484Sobrien for sections. If your COFF flavor has a different way of encoding 166177298Sobrien section alignment, then skip this step, as TICOFF does. */ 1662218822Sdim size = bfd_get_section_size (sec); 166360484Sobrien mask = ((bfd_vma) 1 << align_power) - 1; 166460484Sobrien#if !defined(TICOFF) 166533965Sjdp if (size & mask) 166633965Sjdp { 166777298Sobrien bfd_vma new_size; 166877298Sobrien fragS *last; 166977298Sobrien 167077298Sobrien new_size = (size + mask) & ~mask; 167177298Sobrien bfd_set_section_size (stdoutput, sec, new_size); 167277298Sobrien 167377298Sobrien /* If the size had to be rounded up, add some padding in 167477298Sobrien the last non-empty frag. */ 167577298Sobrien fragp = seg_info (sec)->frchainP->frch_root; 167677298Sobrien last = seg_info (sec)->frchainP->frch_last; 167777298Sobrien while (fragp->fr_next != last) 1678104834Sobrien fragp = fragp->fr_next; 167977298Sobrien last->fr_address = size; 168077298Sobrien fragp->fr_offset += new_size - size; 168133965Sjdp } 168260484Sobrien#endif 168333965Sjdp 168433965Sjdp /* If the section size is non-zero, the section symbol needs an aux 168533965Sjdp entry associated with it, indicating the size. We don't know 168633965Sjdp all the values yet; coff_frob_symbol will fill them in later. */ 168760484Sobrien#ifndef TICOFF 168833965Sjdp if (size != 0 168933965Sjdp || sec == text_section 169033965Sjdp || sec == data_section 169133965Sjdp || sec == bss_section) 169260484Sobrien#endif 169333965Sjdp { 169433965Sjdp symbolS *secsym = section_symbol (sec); 169533965Sjdp 169633965Sjdp S_SET_STORAGE_CLASS (secsym, C_STAT); 169733965Sjdp S_SET_NUMBER_AUXILIARY (secsym, 1); 169833965Sjdp SF_SET_STATICS (secsym); 169933965Sjdp SA_SET_SCN_SCNLEN (secsym, size); 170033965Sjdp } 170133965Sjdp 1702218822Sdim /* FIXME: These should be in a "stabs.h" file, or maybe as.h. */ 170333965Sjdp#ifndef STAB_SECTION_NAME 170433965Sjdp#define STAB_SECTION_NAME ".stab" 170533965Sjdp#endif 170633965Sjdp#ifndef STAB_STRING_SECTION_NAME 170733965Sjdp#define STAB_STRING_SECTION_NAME ".stabstr" 170833965Sjdp#endif 1709218822Sdim if (! streq (STAB_STRING_SECTION_NAME, sec->name)) 171033965Sjdp return; 171133965Sjdp 171233965Sjdp strsec = sec; 171333965Sjdp sec = subseg_get (STAB_SECTION_NAME, 0); 171433965Sjdp /* size is already rounded up, since other section will be listed first */ 1715218822Sdim size = bfd_get_section_size (strsec); 171633965Sjdp 1717218822Sdim n_entries = bfd_get_section_size (sec) / 12 - 1; 171833965Sjdp 171933965Sjdp /* Find first non-empty frag. It should be large enough. */ 172033965Sjdp fragp = seg_info (sec)->frchainP->frch_root; 172133965Sjdp while (fragp && fragp->fr_fix == 0) 172233965Sjdp fragp = fragp->fr_next; 172333965Sjdp assert (fragp != 0 && fragp->fr_fix >= 12); 172433965Sjdp 172533965Sjdp /* Store the values. */ 172633965Sjdp p = fragp->fr_literal; 172733965Sjdp bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6); 172833965Sjdp bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8); 172933965Sjdp} 173033965Sjdp 173133965Sjdpvoid 1732218822Sdimobj_coff_init_stab_section (segT seg) 173333965Sjdp{ 173433965Sjdp char *file; 173533965Sjdp char *p; 173633965Sjdp char *stabstr_name; 173733965Sjdp unsigned int stroff; 173833965Sjdp 173977298Sobrien /* Make space for this first symbol. */ 174033965Sjdp p = frag_more (12); 174177298Sobrien /* Zero it out. */ 174233965Sjdp memset (p, 0, 12); 174333965Sjdp as_where (&file, (unsigned int *) NULL); 1744218822Sdim stabstr_name = xmalloc (strlen (seg->name) + 4); 174533965Sjdp strcpy (stabstr_name, seg->name); 174633965Sjdp strcat (stabstr_name, "str"); 174733965Sjdp stroff = get_stab_string_offset (file, stabstr_name); 174833965Sjdp know (stroff == 1); 174933965Sjdp md_number_to_chars (p, stroff, 4); 175033965Sjdp} 175133965Sjdp 175233965Sjdp#ifdef DEBUG 175333965Sjdpconst char * 1754218822Sdims_get_name (symbolS *s) 175533965Sjdp{ 175633965Sjdp return ((s == NULL) ? "(NULL)" : S_GET_NAME (s)); 175733965Sjdp} 175833965Sjdp 175933965Sjdpvoid 1760218822Sdimsymbol_dump (void) 176133965Sjdp{ 176233965Sjdp symbolS *symbolP; 176333965Sjdp 176433965Sjdp for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) 1765218822Sdim printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"), 1766218822Sdim (unsigned long) symbolP, 1767218822Sdim S_GET_NAME (symbolP), 1768218822Sdim (long) S_GET_DATA_TYPE (symbolP), 1769218822Sdim S_GET_STORAGE_CLASS (symbolP), 1770218822Sdim (int) S_GET_SEGMENT (symbolP)); 177133965Sjdp} 177233965Sjdp 177333965Sjdp#endif /* DEBUG */ 177433965Sjdp 177560484Sobrienconst pseudo_typeS coff_pseudo_table[] = 177633965Sjdp{ 1777218822Sdim {"ABORT", s_abort, 0}, 1778218822Sdim {"appline", obj_coff_ln, 1}, 1779218822Sdim /* We accept the .bss directive for backward compatibility with 1780218822Sdim earlier versions of gas. */ 1781218822Sdim {"bss", obj_coff_bss, 0}, 178233965Sjdp {"def", obj_coff_def, 0}, 178333965Sjdp {"dim", obj_coff_dim, 0}, 178433965Sjdp {"endef", obj_coff_endef, 0}, 1785218822Sdim {"ident", obj_coff_ident, 0}, 178633965Sjdp {"line", obj_coff_line, 0}, 178733965Sjdp {"ln", obj_coff_ln, 0}, 178833965Sjdp {"scl", obj_coff_scl, 0}, 1789218822Sdim {"sect", obj_coff_section, 0}, 1790218822Sdim {"sect.s", obj_coff_section, 0}, 1791218822Sdim {"section", obj_coff_section, 0}, 1792218822Sdim {"section.s", obj_coff_section, 0}, 1793218822Sdim /* FIXME: We ignore the MRI short attribute. */ 179433965Sjdp {"size", obj_coff_size, 0}, 179533965Sjdp {"tag", obj_coff_tag, 0}, 179633965Sjdp {"type", obj_coff_type, 0}, 179733965Sjdp {"val", obj_coff_val, 0}, 1798218822Sdim {"version", s_ignore, 0}, 1799218822Sdim {"loc", obj_coff_loc, 0}, 1800218822Sdim {"optim", s_ignore, 0}, /* For sun386i cc (?) */ 180160484Sobrien {"weak", obj_coff_weak, 0}, 1802218822Sdim#if defined TC_TIC4X 1803218822Sdim /* The tic4x uses sdef instead of def. */ 180433965Sjdp {"sdef", obj_coff_def, 0}, 180533965Sjdp#endif 1806218822Sdim {NULL, NULL, 0} 1807218822Sdim}; 180833965Sjdp 180933965Sjdp 181033965Sjdp/* Support for a COFF emulation. */ 181133965Sjdp 181233965Sjdpstatic void 1813218822Sdimcoff_pop_insert (void) 181433965Sjdp{ 181560484Sobrien pop_insert (coff_pseudo_table); 181633965Sjdp} 181733965Sjdp 181877298Sobrienstatic int 1819218822Sdimcoff_separate_stab_sections (void) 182077298Sobrien{ 182177298Sobrien return 1; 182277298Sobrien} 182377298Sobrien 182433965Sjdpconst struct format_ops coff_format_ops = 182533965Sjdp{ 182633965Sjdp bfd_target_coff_flavour, 182760484Sobrien 0, /* dfl_leading_underscore */ 182860484Sobrien 1, /* emit_section_symbols */ 182977298Sobrien 0, /* begin */ 183077298Sobrien c_dot_file_symbol, 183133965Sjdp coff_frob_symbol, 183260484Sobrien 0, /* frob_file */ 183377298Sobrien 0, /* frob_file_before_adjust */ 1834130561Sobrien 0, /* frob_file_before_fix */ 183538889Sjdp coff_frob_file_after_relocs, 183660484Sobrien 0, /* s_get_size */ 183760484Sobrien 0, /* s_set_size */ 183860484Sobrien 0, /* s_get_align */ 183960484Sobrien 0, /* s_set_align */ 184060484Sobrien 0, /* s_get_other */ 184177298Sobrien 0, /* s_set_other */ 184260484Sobrien 0, /* s_get_desc */ 184377298Sobrien 0, /* s_set_desc */ 184477298Sobrien 0, /* s_get_type */ 184577298Sobrien 0, /* s_set_type */ 184660484Sobrien 0, /* copy_symbol_attributes */ 184760484Sobrien 0, /* generate_asm_lineno */ 184860484Sobrien 0, /* process_stab */ 184977298Sobrien coff_separate_stab_sections, 185077298Sobrien obj_coff_init_stab_section, 185160484Sobrien 0, /* sec_sym_ok_for_reloc */ 185233965Sjdp coff_pop_insert, 185360484Sobrien 0, /* ecoff_set_ext */ 185433965Sjdp coff_obj_read_begin_hook, 185560484Sobrien coff_obj_symbol_new_hook 185633965Sjdp}; 1857