symbols.c revision 130561
133965Sjdp/* symbols.c -symbol table- 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3130561Sobrien 1999, 2000, 2001, 2002, 2003 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS, the GNU Assembler. 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 2033965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2133965Sjdp 02111-1307, USA. */ 2233965Sjdp 2377298Sobrien/* #define DEBUG_SYMS / * to debug symbol list maintenance. */ 2433965Sjdp 2533965Sjdp#include "as.h" 2633965Sjdp 2789857Sobrien#include "safe-ctype.h" 2833965Sjdp#include "obstack.h" /* For "symbols.h" */ 2933965Sjdp#include "subsegs.h" 3033965Sjdp 3160484Sobrien#include "struc-symbol.h" 3260484Sobrien 3333965Sjdp/* This is non-zero if symbols are case sensitive, which is the 3433965Sjdp default. */ 3533965Sjdpint symbols_case_sensitive = 1; 3633965Sjdp 3733965Sjdp#ifndef WORKING_DOT_WORD 3833965Sjdpextern int new_broken_words; 3933965Sjdp#endif 4033965Sjdp 4133965Sjdp/* symbol-name => struct symbol pointer */ 4233965Sjdpstatic struct hash_control *sy_hash; 4333965Sjdp 4460484Sobrien/* Table of local symbols. */ 4560484Sobrienstatic struct hash_control *local_hash; 4660484Sobrien 4777298Sobrien/* Below are commented in "symbols.h". */ 4833965SjdpsymbolS *symbol_rootP; 4933965SjdpsymbolS *symbol_lastP; 5033965SjdpsymbolS abs_symbol; 5133965Sjdp 5233965Sjdp#ifdef DEBUG_SYMS 5333965Sjdp#define debug_verify_symchain verify_symbol_chain 5433965Sjdp#else 5533965Sjdp#define debug_verify_symchain(root, last) ((void) 0) 5633965Sjdp#endif 5733965Sjdp 5877298Sobrien#define DOLLAR_LABEL_CHAR '\001' 5977298Sobrien#define LOCAL_LABEL_CHAR '\002' 6077298Sobrien 6133965Sjdpstruct obstack notes; 6233965Sjdp 63130561Sobrienstatic char *save_symbol_name (const char *); 64130561Sobrienstatic void fb_label_init (void); 65130561Sobrienstatic long dollar_label_instance (long); 66130561Sobrienstatic long fb_label_instance (long); 6733965Sjdp 68130561Sobrienstatic void print_binary (FILE *, const char *, expressionS *); 69130561Sobrienstatic void report_op_error (symbolS *, symbolS *, symbolS *); 7060484Sobrien 7177298Sobrien/* Return a pointer to a new symbol. Die if we can't make a new 7233965Sjdp symbol. Fill in the symbol's values. Add symbol to end of symbol 7333965Sjdp chain. 7477298Sobrien 7533965Sjdp This function should be called in the general case of creating a 7633965Sjdp symbol. However, if the output file symbol table has already been 7733965Sjdp set, and you are certain that this symbol won't be wanted in the 7833965Sjdp output file, you can call symbol_create. */ 7933965Sjdp 8033965SjdpsymbolS * 81130561Sobriensymbol_new (const char *name, segT segment, valueT valu, fragS *frag) 8233965Sjdp{ 8333965Sjdp symbolS *symbolP = symbol_create (name, segment, valu, frag); 8433965Sjdp 8577298Sobrien /* Link to end of symbol chain. */ 8633965Sjdp#ifdef BFD_ASSEMBLER 8733965Sjdp { 8833965Sjdp extern int symbol_table_frozen; 8933965Sjdp if (symbol_table_frozen) 9033965Sjdp abort (); 9133965Sjdp } 9233965Sjdp#endif 9333965Sjdp symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP); 9433965Sjdp 9533965Sjdp return symbolP; 9633965Sjdp} 9733965Sjdp 9860484Sobrien/* Save a symbol name on a permanent obstack, and convert it according 9960484Sobrien to the object file format. */ 10060484Sobrien 10160484Sobrienstatic char * 102130561Sobriensave_symbol_name (const char *name) 10333965Sjdp{ 10433965Sjdp unsigned int name_length; 10560484Sobrien char *ret; 10633965Sjdp 10777298Sobrien name_length = strlen (name) + 1; /* +1 for \0. */ 10833965Sjdp obstack_grow (¬es, name, name_length); 10960484Sobrien ret = obstack_finish (¬es); 11060484Sobrien 11133965Sjdp#ifdef STRIP_UNDERSCORE 11260484Sobrien if (ret[0] == '_') 11360484Sobrien ++ret; 11433965Sjdp#endif 11533965Sjdp 11633965Sjdp#ifdef tc_canonicalize_symbol_name 11760484Sobrien ret = tc_canonicalize_symbol_name (ret); 11833965Sjdp#endif 11933965Sjdp 12033965Sjdp if (! symbols_case_sensitive) 12133965Sjdp { 12289857Sobrien char *s; 12333965Sjdp 12489857Sobrien for (s = ret; *s != '\0'; s++) 12589857Sobrien *s = TOUPPER (*s); 12633965Sjdp } 12733965Sjdp 12860484Sobrien return ret; 12960484Sobrien} 13060484Sobrien 13160484SobriensymbolS * 132130561Sobriensymbol_create (const char *name, /* It is copied, the caller can destroy/modify. */ 133130561Sobrien segT segment, /* Segment identifier (SEG_<something>). */ 134130561Sobrien valueT valu, /* Symbol value. */ 135130561Sobrien fragS *frag /* Associated fragment. */) 13660484Sobrien{ 13760484Sobrien char *preserved_copy_of_name; 13860484Sobrien symbolS *symbolP; 13960484Sobrien 14060484Sobrien preserved_copy_of_name = save_symbol_name (name); 14160484Sobrien 14233965Sjdp symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS)); 14333965Sjdp 14477298Sobrien /* symbol must be born in some fixed state. This seems as good as any. */ 14533965Sjdp memset (symbolP, 0, sizeof (symbolS)); 14633965Sjdp 14733965Sjdp#ifdef BFD_ASSEMBLER 14833965Sjdp symbolP->bsym = bfd_make_empty_symbol (stdoutput); 14933965Sjdp if (symbolP->bsym == NULL) 15033965Sjdp as_perror ("%s", "bfd_make_empty_symbol"); 15133965Sjdp symbolP->bsym->udata.p = (PTR) symbolP; 15233965Sjdp#endif 15333965Sjdp S_SET_NAME (symbolP, preserved_copy_of_name); 15433965Sjdp 15533965Sjdp S_SET_SEGMENT (symbolP, segment); 15633965Sjdp S_SET_VALUE (symbolP, valu); 15733965Sjdp symbol_clear_list_pointers (symbolP); 15833965Sjdp 15933965Sjdp symbolP->sy_frag = frag; 16033965Sjdp#ifndef BFD_ASSEMBLER 16133965Sjdp symbolP->sy_number = ~0; 16233965Sjdp symbolP->sy_name_offset = (unsigned int) ~0; 16333965Sjdp#endif 16433965Sjdp 16533965Sjdp obj_symbol_new_hook (symbolP); 16633965Sjdp 16733965Sjdp#ifdef tc_symbol_new_hook 16833965Sjdp tc_symbol_new_hook (symbolP); 16933965Sjdp#endif 17033965Sjdp 17133965Sjdp return symbolP; 17233965Sjdp} 17333965Sjdp 17460484Sobrien#ifdef BFD_ASSEMBLER 17533965Sjdp 17660484Sobrien/* Local symbol support. If we can get away with it, we keep only a 17760484Sobrien small amount of information for local symbols. */ 17860484Sobrien 179130561Sobrienstatic symbolS *local_symbol_convert (struct local_symbol *); 18060484Sobrien 18160484Sobrien/* Used for statistics. */ 18260484Sobrien 18360484Sobrienstatic unsigned long local_symbol_count; 18460484Sobrienstatic unsigned long local_symbol_conversion_count; 18560484Sobrien 18660484Sobrien/* This macro is called with a symbol argument passed by reference. 18760484Sobrien It returns whether this is a local symbol. If necessary, it 18860484Sobrien changes its argument to the real symbol. */ 18960484Sobrien 19060484Sobrien#define LOCAL_SYMBOL_CHECK(s) \ 19160484Sobrien (s->bsym == NULL \ 19260484Sobrien ? (local_symbol_converted_p ((struct local_symbol *) s) \ 19360484Sobrien ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s), \ 19460484Sobrien 0) \ 19560484Sobrien : 1) \ 19660484Sobrien : 0) 19760484Sobrien 19860484Sobrien/* Create a local symbol and insert it into the local hash table. */ 19960484Sobrien 200130561Sobrienstruct local_symbol * 201130561Sobrienlocal_symbol_make (const char *name, segT section, valueT value, fragS *frag) 20260484Sobrien{ 20360484Sobrien char *name_copy; 20460484Sobrien struct local_symbol *ret; 20560484Sobrien 20660484Sobrien ++local_symbol_count; 20760484Sobrien 20860484Sobrien name_copy = save_symbol_name (name); 20960484Sobrien 21060484Sobrien ret = (struct local_symbol *) obstack_alloc (¬es, sizeof *ret); 21160484Sobrien ret->lsy_marker = NULL; 21260484Sobrien ret->lsy_name = name_copy; 21360484Sobrien ret->lsy_section = section; 21460484Sobrien local_symbol_set_frag (ret, frag); 21589857Sobrien ret->lsy_value = value; 21660484Sobrien 21760484Sobrien hash_jam (local_hash, name_copy, (PTR) ret); 21860484Sobrien 21960484Sobrien return ret; 22060484Sobrien} 22160484Sobrien 22260484Sobrien/* Convert a local symbol into a real symbol. Note that we do not 22360484Sobrien reclaim the space used by the local symbol. */ 22460484Sobrien 22560484Sobrienstatic symbolS * 226130561Sobrienlocal_symbol_convert (struct local_symbol *locsym) 22760484Sobrien{ 22860484Sobrien symbolS *ret; 22960484Sobrien 23060484Sobrien assert (locsym->lsy_marker == NULL); 23160484Sobrien if (local_symbol_converted_p (locsym)) 23260484Sobrien return local_symbol_get_real_symbol (locsym); 23360484Sobrien 23460484Sobrien ++local_symbol_conversion_count; 23560484Sobrien 23689857Sobrien ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value, 23760484Sobrien local_symbol_get_frag (locsym)); 23860484Sobrien 23960484Sobrien if (local_symbol_resolved_p (locsym)) 24060484Sobrien ret->sy_resolved = 1; 24160484Sobrien 24260484Sobrien /* Local symbols are always either defined or used. */ 24360484Sobrien ret->sy_used = 1; 24460484Sobrien 24589857Sobrien#ifdef TC_LOCAL_SYMFIELD_CONVERT 24689857Sobrien TC_LOCAL_SYMFIELD_CONVERT (locsym, ret); 24789857Sobrien#endif 24889857Sobrien 24960484Sobrien symbol_table_insert (ret); 25060484Sobrien 25160484Sobrien local_symbol_mark_converted (locsym); 25260484Sobrien local_symbol_set_real_symbol (locsym, ret); 25360484Sobrien 25460484Sobrien hash_jam (local_hash, locsym->lsy_name, NULL); 25560484Sobrien 25660484Sobrien return ret; 25760484Sobrien} 25860484Sobrien 25960484Sobrien#else /* ! BFD_ASSEMBLER */ 26060484Sobrien 26160484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0 26260484Sobrien#define local_symbol_convert(s) ((symbolS *) s) 26360484Sobrien 26460484Sobrien#endif /* ! BFD_ASSEMBLER */ 26560484Sobrien 26677298Sobrien/* We have just seen "<name>:". 26777298Sobrien Creates a struct symbol unless it already exists. 26860484Sobrien 26977298Sobrien Gripes if we are redefining a symbol incompatibly (and ignores it). */ 27077298Sobrien 27133965SjdpsymbolS * 272130561Sobriencolon (/* Just seen "x:" - rattle symbols & frags. */ 273130561Sobrien const char *sym_name /* Symbol name, as a cannonical string. */ 274130561Sobrien /* We copy this string: OK to alter later. */) 27533965Sjdp{ 27677298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 27733965Sjdp 27833965Sjdp /* Sun local labels go out of scope whenever a non-local symbol is 27933965Sjdp defined. */ 28033965Sjdp if (LOCAL_LABELS_DOLLAR) 28133965Sjdp { 28233965Sjdp int local; 28333965Sjdp 28433965Sjdp#ifdef BFD_ASSEMBLER 28533965Sjdp local = bfd_is_local_label_name (stdoutput, sym_name); 28633965Sjdp#else 28733965Sjdp local = LOCAL_LABEL (sym_name); 28833965Sjdp#endif 28933965Sjdp 29033965Sjdp if (! local) 29133965Sjdp dollar_label_clear (); 29233965Sjdp } 29333965Sjdp 29433965Sjdp#ifndef WORKING_DOT_WORD 29533965Sjdp if (new_broken_words) 29633965Sjdp { 29733965Sjdp struct broken_word *a; 29833965Sjdp int possible_bytes; 29933965Sjdp fragS *frag_tmp; 30033965Sjdp char *frag_opcode; 30133965Sjdp 30233965Sjdp extern const int md_short_jump_size; 30333965Sjdp extern const int md_long_jump_size; 304130561Sobrien 305130561Sobrien if (now_seg == absolute_section) 306130561Sobrien { 307130561Sobrien as_bad (_("cannot define symbol `%s' in absolute section"), sym_name); 308130561Sobrien return NULL; 309130561Sobrien } 310130561Sobrien 31133965Sjdp possible_bytes = (md_short_jump_size 31233965Sjdp + new_broken_words * md_long_jump_size); 31333965Sjdp 31433965Sjdp frag_tmp = frag_now; 31533965Sjdp frag_opcode = frag_var (rs_broken_word, 31633965Sjdp possible_bytes, 31733965Sjdp possible_bytes, 31833965Sjdp (relax_substateT) 0, 31933965Sjdp (symbolS *) broken_words, 32033965Sjdp (offsetT) 0, 32133965Sjdp NULL); 32233965Sjdp 32377298Sobrien /* We want to store the pointer to where to insert the jump 32477298Sobrien table in the fr_opcode of the rs_broken_word frag. This 32577298Sobrien requires a little hackery. */ 32633965Sjdp while (frag_tmp 32733965Sjdp && (frag_tmp->fr_type != rs_broken_word 32833965Sjdp || frag_tmp->fr_opcode)) 32933965Sjdp frag_tmp = frag_tmp->fr_next; 33033965Sjdp know (frag_tmp); 33133965Sjdp frag_tmp->fr_opcode = frag_opcode; 33233965Sjdp new_broken_words = 0; 33333965Sjdp 33433965Sjdp for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word) 33533965Sjdp a->dispfrag = frag_tmp; 33633965Sjdp } 33733965Sjdp#endif /* WORKING_DOT_WORD */ 33833965Sjdp 33933965Sjdp if ((symbolP = symbol_find (sym_name)) != 0) 34033965Sjdp { 34133965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION 34233965Sjdp if (RESOLVE_SYMBOL_REDEFINITION (symbolP)) 34333965Sjdp return symbolP; 34433965Sjdp#endif 34577298Sobrien /* Now check for undefined symbols. */ 34660484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 34733965Sjdp { 34860484Sobrien#ifdef BFD_ASSEMBLER 34960484Sobrien struct local_symbol *locsym = (struct local_symbol *) symbolP; 35060484Sobrien 35160484Sobrien if (locsym->lsy_section != undefined_section 35260484Sobrien && (local_symbol_get_frag (locsym) != frag_now 35360484Sobrien || locsym->lsy_section != now_seg 35489857Sobrien || locsym->lsy_value != frag_now_fix ())) 35560484Sobrien { 35689857Sobrien as_bad (_("symbol `%s' is already defined"), sym_name); 35760484Sobrien return symbolP; 35860484Sobrien } 35960484Sobrien 36060484Sobrien locsym->lsy_section = now_seg; 36160484Sobrien local_symbol_set_frag (locsym, frag_now); 36289857Sobrien locsym->lsy_value = frag_now_fix (); 36360484Sobrien#endif 36460484Sobrien } 36560484Sobrien else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 36660484Sobrien { 36733965Sjdp if (S_GET_VALUE (symbolP) == 0) 36833965Sjdp { 36933965Sjdp symbolP->sy_frag = frag_now; 37033965Sjdp#ifdef OBJ_VMS 37177298Sobrien S_SET_OTHER (symbolP, const_flag); 37233965Sjdp#endif 37333965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 37433965Sjdp S_SET_SEGMENT (symbolP, now_seg); 37533965Sjdp#ifdef N_UNDF 37633965Sjdp know (N_UNDF == 0); 37777298Sobrien#endif /* if we have one, it better be zero. */ 37833965Sjdp 37933965Sjdp } 38033965Sjdp else 38133965Sjdp { 38277298Sobrien /* There are still several cases to check: 38333965Sjdp 38477298Sobrien A .comm/.lcomm symbol being redefined as initialized 38577298Sobrien data is OK 38677298Sobrien 38777298Sobrien A .comm/.lcomm symbol being redefined with a larger 38877298Sobrien size is also OK 38977298Sobrien 39077298Sobrien This only used to be allowed on VMS gas, but Sun cc 39177298Sobrien on the sparc also depends on it. */ 39277298Sobrien 39333965Sjdp if (((!S_IS_DEBUG (symbolP) 39433965Sjdp && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 39533965Sjdp && S_IS_EXTERNAL (symbolP)) 39633965Sjdp || S_GET_SEGMENT (symbolP) == bss_section) 39733965Sjdp && (now_seg == data_section 39833965Sjdp || now_seg == S_GET_SEGMENT (symbolP))) 39933965Sjdp { 40077298Sobrien /* Select which of the 2 cases this is. */ 40133965Sjdp if (now_seg != data_section) 40233965Sjdp { 40377298Sobrien /* New .comm for prev .comm symbol. 40477298Sobrien 40577298Sobrien If the new size is larger we just change its 40677298Sobrien value. If the new size is smaller, we ignore 40777298Sobrien this symbol. */ 40833965Sjdp if (S_GET_VALUE (symbolP) 40933965Sjdp < ((unsigned) frag_now_fix ())) 41033965Sjdp { 41133965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 41233965Sjdp } 41333965Sjdp } 41433965Sjdp else 41533965Sjdp { 41633965Sjdp /* It is a .comm/.lcomm being converted to initialized 41733965Sjdp data. */ 41833965Sjdp symbolP->sy_frag = frag_now; 41933965Sjdp#ifdef OBJ_VMS 42077298Sobrien S_SET_OTHER (symbolP, const_flag); 42133965Sjdp#endif 42233965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 42377298Sobrien S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit. */ 42433965Sjdp } 42533965Sjdp } 42633965Sjdp else 42733965Sjdp { 42860484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \ 42960484Sobrien && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT)) 43060484Sobrien static const char *od_buf = ""; 43133965Sjdp#else 43260484Sobrien char od_buf[100]; 43360484Sobrien od_buf[0] = '\0'; 43460484Sobrien#ifdef BFD_ASSEMBLER 43560484Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 43660484Sobrien#endif 437104834Sobrien sprintf (od_buf, "%d.%d.", 438104834Sobrien S_GET_OTHER (symbolP), 439104834Sobrien S_GET_DESC (symbolP)); 44060484Sobrien#endif 44189857Sobrien as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"), 44233965Sjdp sym_name, 44333965Sjdp segment_name (S_GET_SEGMENT (symbolP)), 44460484Sobrien od_buf, 44533965Sjdp (long) S_GET_VALUE (symbolP)); 44633965Sjdp } 44777298Sobrien } /* if the undefined symbol has no value */ 44833965Sjdp } 44933965Sjdp else 45033965Sjdp { 45177298Sobrien /* Don't blow up if the definition is the same. */ 45233965Sjdp if (!(frag_now == symbolP->sy_frag 45333965Sjdp && S_GET_VALUE (symbolP) == frag_now_fix () 45433965Sjdp && S_GET_SEGMENT (symbolP) == now_seg)) 45589857Sobrien as_bad (_("symbol `%s' is already defined"), sym_name); 45677298Sobrien } 45733965Sjdp 45833965Sjdp } 45960484Sobrien#ifdef BFD_ASSEMBLER 46060484Sobrien else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name)) 46160484Sobrien { 46260484Sobrien symbolP = (symbolS *) local_symbol_make (sym_name, now_seg, 46360484Sobrien (valueT) frag_now_fix (), 46460484Sobrien frag_now); 46560484Sobrien } 46660484Sobrien#endif /* BFD_ASSEMBLER */ 46733965Sjdp else 46833965Sjdp { 46933965Sjdp symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (), 47033965Sjdp frag_now); 47133965Sjdp#ifdef OBJ_VMS 47233965Sjdp S_SET_OTHER (symbolP, const_flag); 47333965Sjdp#endif /* OBJ_VMS */ 47433965Sjdp 47533965Sjdp symbol_table_insert (symbolP); 47677298Sobrien } 47733965Sjdp 47833965Sjdp if (mri_common_symbol != NULL) 47933965Sjdp { 48033965Sjdp /* This symbol is actually being defined within an MRI common 481130561Sobrien section. This requires special handling. */ 48260484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 48360484Sobrien symbolP = local_symbol_convert ((struct local_symbol *) symbolP); 48433965Sjdp symbolP->sy_value.X_op = O_symbol; 48533965Sjdp symbolP->sy_value.X_add_symbol = mri_common_symbol; 48633965Sjdp symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol); 48733965Sjdp symbolP->sy_frag = &zero_address_frag; 48833965Sjdp S_SET_SEGMENT (symbolP, expr_section); 48933965Sjdp symbolP->sy_mri_common = 1; 49033965Sjdp } 49133965Sjdp 49233965Sjdp#ifdef tc_frob_label 49333965Sjdp tc_frob_label (symbolP); 49433965Sjdp#endif 49533965Sjdp#ifdef obj_frob_label 49633965Sjdp obj_frob_label (symbolP); 49733965Sjdp#endif 49833965Sjdp 49933965Sjdp return symbolP; 50033965Sjdp} 50133965Sjdp 50277298Sobrien/* Die if we can't insert the symbol. */ 50333965Sjdp 50477298Sobrienvoid 505130561Sobriensymbol_table_insert (symbolS *symbolP) 50633965Sjdp{ 50733965Sjdp register const char *error_string; 50833965Sjdp 50933965Sjdp know (symbolP); 51033965Sjdp know (S_GET_NAME (symbolP)); 51133965Sjdp 51260484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 51360484Sobrien { 51460484Sobrien error_string = hash_jam (local_hash, S_GET_NAME (symbolP), 51560484Sobrien (PTR) symbolP); 51660484Sobrien if (error_string != NULL) 51789857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 51860484Sobrien S_GET_NAME (symbolP), error_string); 51960484Sobrien return; 52060484Sobrien } 52160484Sobrien 52233965Sjdp if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP))) 52333965Sjdp { 52489857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 52533965Sjdp S_GET_NAME (symbolP), error_string); 52677298Sobrien } /* on error */ 52777298Sobrien} 52833965Sjdp 52977298Sobrien/* If a symbol name does not exist, create it as undefined, and insert 53077298Sobrien it into the symbol table. Return a pointer to it. */ 53177298Sobrien 53233965SjdpsymbolS * 533130561Sobriensymbol_find_or_make (const char *name) 53433965Sjdp{ 53533965Sjdp register symbolS *symbolP; 53633965Sjdp 53733965Sjdp symbolP = symbol_find (name); 53833965Sjdp 53933965Sjdp if (symbolP == NULL) 54033965Sjdp { 54160484Sobrien#ifdef BFD_ASSEMBLER 54260484Sobrien if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name)) 54360484Sobrien { 54460484Sobrien symbolP = md_undefined_symbol ((char *) name); 54560484Sobrien if (symbolP != NULL) 54660484Sobrien return symbolP; 54760484Sobrien 54860484Sobrien symbolP = (symbolS *) local_symbol_make (name, undefined_section, 54960484Sobrien (valueT) 0, 55060484Sobrien &zero_address_frag); 55160484Sobrien return symbolP; 55260484Sobrien } 55360484Sobrien#endif 55460484Sobrien 55533965Sjdp symbolP = symbol_make (name); 55633965Sjdp 55733965Sjdp symbol_table_insert (symbolP); 55833965Sjdp } /* if symbol wasn't found */ 55933965Sjdp 56033965Sjdp return (symbolP); 56177298Sobrien} 56233965Sjdp 56333965SjdpsymbolS * 564130561Sobriensymbol_make (const char *name) 56533965Sjdp{ 56633965Sjdp symbolS *symbolP; 56733965Sjdp 56877298Sobrien /* Let the machine description default it, e.g. for register names. */ 56933965Sjdp symbolP = md_undefined_symbol ((char *) name); 57033965Sjdp 57133965Sjdp if (!symbolP) 57233965Sjdp symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag); 57333965Sjdp 57433965Sjdp return (symbolP); 57577298Sobrien} 57633965Sjdp 577130561SobriensymbolS * 578130561Sobriensymbol_temp_new (segT seg, valueT ofs, fragS *frag) 579130561Sobrien{ 580130561Sobrien return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag); 581130561Sobrien} 582130561Sobrien 583130561SobriensymbolS * 584130561Sobriensymbol_temp_new_now (void) 585130561Sobrien{ 586130561Sobrien return symbol_temp_new (now_seg, frag_now_fix (), frag_now); 587130561Sobrien} 588130561Sobrien 589130561SobriensymbolS * 590130561Sobriensymbol_temp_make (void) 591130561Sobrien{ 592130561Sobrien return symbol_make (FAKE_LABEL_NAME); 593130561Sobrien} 594130561Sobrien 59577298Sobrien/* Implement symbol table lookup. 59677298Sobrien In: A symbol's name as a string: '\0' can't be part of a symbol name. 59777298Sobrien Out: NULL if the name was not in the symbol table, else the address 59877298Sobrien of a struct symbol associated with that name. */ 59933965Sjdp 60033965SjdpsymbolS * 601130561Sobriensymbol_find (const char *name) 60233965Sjdp{ 60333965Sjdp#ifdef STRIP_UNDERSCORE 60433965Sjdp return (symbol_find_base (name, 1)); 60533965Sjdp#else /* STRIP_UNDERSCORE */ 60633965Sjdp return (symbol_find_base (name, 0)); 60733965Sjdp#endif /* STRIP_UNDERSCORE */ 60877298Sobrien} 60933965Sjdp 61033965SjdpsymbolS * 611130561Sobriensymbol_find_exact (const char *name) 612104834Sobrien{ 613104834Sobrien#ifdef BFD_ASSEMBLER 614104834Sobrien { 615104834Sobrien struct local_symbol *locsym; 616104834Sobrien 617104834Sobrien locsym = (struct local_symbol *) hash_find (local_hash, name); 618104834Sobrien if (locsym != NULL) 619104834Sobrien return (symbolS *) locsym; 620104834Sobrien } 621104834Sobrien#endif 622104834Sobrien 623104834Sobrien return ((symbolS *) hash_find (sy_hash, name)); 624104834Sobrien} 625104834Sobrien 626104834SobriensymbolS * 627130561Sobriensymbol_find_base (const char *name, int strip_underscore) 62833965Sjdp{ 62933965Sjdp if (strip_underscore && *name == '_') 63033965Sjdp name++; 63133965Sjdp 63233965Sjdp#ifdef tc_canonicalize_symbol_name 63333965Sjdp { 63433965Sjdp char *copy; 63560484Sobrien size_t len = strlen (name) + 1; 63633965Sjdp 63760484Sobrien copy = (char *) alloca (len); 63860484Sobrien memcpy (copy, name, len); 63933965Sjdp name = tc_canonicalize_symbol_name (copy); 64033965Sjdp } 64133965Sjdp#endif 64233965Sjdp 64333965Sjdp if (! symbols_case_sensitive) 64433965Sjdp { 64560484Sobrien char *copy; 64660484Sobrien const char *orig; 64760484Sobrien unsigned char c; 64833965Sjdp 64960484Sobrien orig = name; 65060484Sobrien name = copy = (char *) alloca (strlen (name) + 1); 65160484Sobrien 65260484Sobrien while ((c = *orig++) != '\0') 65360484Sobrien { 65489857Sobrien *copy++ = TOUPPER (c); 65560484Sobrien } 65660484Sobrien *copy = '\0'; 65733965Sjdp } 65833965Sjdp 659104834Sobrien return symbol_find_exact (name); 66033965Sjdp} 66133965Sjdp 66277298Sobrien/* Once upon a time, symbols were kept in a singly linked list. At 66377298Sobrien least coff needs to be able to rearrange them from time to time, for 66477298Sobrien which a doubly linked list is much more convenient. Loic did these 66577298Sobrien as macros which seemed dangerous to me so they're now functions. 66677298Sobrien xoxorich. */ 66733965Sjdp 66877298Sobrien/* Link symbol ADDME after symbol TARGET in the chain. */ 66977298Sobrien 67077298Sobrienvoid 671130561Sobriensymbol_append (symbolS *addme, symbolS *target, 672130561Sobrien symbolS **rootPP, symbolS **lastPP) 67333965Sjdp{ 67460484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 67560484Sobrien abort (); 67660484Sobrien if (target != NULL && LOCAL_SYMBOL_CHECK (target)) 67760484Sobrien abort (); 67860484Sobrien 67933965Sjdp if (target == NULL) 68033965Sjdp { 68133965Sjdp know (*rootPP == NULL); 68233965Sjdp know (*lastPP == NULL); 68333965Sjdp addme->sy_next = NULL; 68433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 68533965Sjdp addme->sy_previous = NULL; 68633965Sjdp#endif 68733965Sjdp *rootPP = addme; 68833965Sjdp *lastPP = addme; 68933965Sjdp return; 69077298Sobrien } /* if the list is empty */ 69133965Sjdp 69233965Sjdp if (target->sy_next != NULL) 69333965Sjdp { 69433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 69533965Sjdp target->sy_next->sy_previous = addme; 69633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 69733965Sjdp } 69833965Sjdp else 69933965Sjdp { 70033965Sjdp know (*lastPP == target); 70133965Sjdp *lastPP = addme; 70277298Sobrien } /* if we have a next */ 70333965Sjdp 70433965Sjdp addme->sy_next = target->sy_next; 70533965Sjdp target->sy_next = addme; 70633965Sjdp 70733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 70833965Sjdp addme->sy_previous = target; 70933965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 71033965Sjdp 71133965Sjdp debug_verify_symchain (symbol_rootP, symbol_lastP); 71233965Sjdp} 71333965Sjdp 71477298Sobrien/* Set the chain pointers of SYMBOL to null. */ 71577298Sobrien 71677298Sobrienvoid 717130561Sobriensymbol_clear_list_pointers (symbolS *symbolP) 71833965Sjdp{ 71960484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 72060484Sobrien abort (); 72133965Sjdp symbolP->sy_next = NULL; 72233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 72333965Sjdp symbolP->sy_previous = NULL; 72433965Sjdp#endif 72533965Sjdp} 72633965Sjdp 72733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 72877298Sobrien/* Remove SYMBOLP from the list. */ 72977298Sobrien 73077298Sobrienvoid 731130561Sobriensymbol_remove (symbolS *symbolP, symbolS **rootPP, symbolS **lastPP) 73233965Sjdp{ 73360484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 73460484Sobrien abort (); 73560484Sobrien 73633965Sjdp if (symbolP == *rootPP) 73733965Sjdp { 73833965Sjdp *rootPP = symbolP->sy_next; 73977298Sobrien } /* if it was the root */ 74033965Sjdp 74133965Sjdp if (symbolP == *lastPP) 74233965Sjdp { 74333965Sjdp *lastPP = symbolP->sy_previous; 74477298Sobrien } /* if it was the tail */ 74533965Sjdp 74633965Sjdp if (symbolP->sy_next != NULL) 74733965Sjdp { 74833965Sjdp symbolP->sy_next->sy_previous = symbolP->sy_previous; 74977298Sobrien } /* if not last */ 75033965Sjdp 75133965Sjdp if (symbolP->sy_previous != NULL) 75233965Sjdp { 75333965Sjdp symbolP->sy_previous->sy_next = symbolP->sy_next; 75477298Sobrien } /* if not first */ 75533965Sjdp 75633965Sjdp debug_verify_symchain (*rootPP, *lastPP); 75733965Sjdp} 75833965Sjdp 75977298Sobrien/* Link symbol ADDME before symbol TARGET in the chain. */ 76077298Sobrien 76177298Sobrienvoid 762130561Sobriensymbol_insert (symbolS *addme, symbolS *target, 763130561Sobrien symbolS **rootPP, symbolS **lastPP ATTRIBUTE_UNUSED) 76433965Sjdp{ 76560484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 76660484Sobrien abort (); 76760484Sobrien if (LOCAL_SYMBOL_CHECK (target)) 76860484Sobrien abort (); 76960484Sobrien 77033965Sjdp if (target->sy_previous != NULL) 77133965Sjdp { 77233965Sjdp target->sy_previous->sy_next = addme; 77333965Sjdp } 77433965Sjdp else 77533965Sjdp { 77633965Sjdp know (*rootPP == target); 77733965Sjdp *rootPP = addme; 77877298Sobrien } /* if not first */ 77933965Sjdp 78033965Sjdp addme->sy_previous = target->sy_previous; 78133965Sjdp target->sy_previous = addme; 78233965Sjdp addme->sy_next = target; 78333965Sjdp 78433965Sjdp debug_verify_symchain (*rootPP, *lastPP); 78533965Sjdp} 78633965Sjdp 78733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 78833965Sjdp 78977298Sobrienvoid 790130561Sobrienverify_symbol_chain (symbolS *rootP, symbolS *lastP) 79133965Sjdp{ 79233965Sjdp symbolS *symbolP = rootP; 79333965Sjdp 79433965Sjdp if (symbolP == NULL) 79533965Sjdp return; 79633965Sjdp 79733965Sjdp for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) 79833965Sjdp { 79960484Sobrien#ifdef BFD_ASSEMBLER 80060484Sobrien assert (symbolP->bsym != NULL); 80160484Sobrien#endif 80233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 80333965Sjdp assert (symbolP->sy_next->sy_previous == symbolP); 80433965Sjdp#else 80533965Sjdp /* Walk the list anyways, to make sure pointers are still good. */ 80633965Sjdp ; 80733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 80833965Sjdp } 80933965Sjdp 81033965Sjdp assert (lastP == symbolP); 81133965Sjdp} 81233965Sjdp 81333965Sjdpvoid 814130561Sobrienverify_symbol_chain_2 (symbolS *sym) 81533965Sjdp{ 81633965Sjdp symbolS *p = sym, *n = sym; 81733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 81833965Sjdp while (symbol_previous (p)) 81933965Sjdp p = symbol_previous (p); 82033965Sjdp#endif 82133965Sjdp while (symbol_next (n)) 82233965Sjdp n = symbol_next (n); 82333965Sjdp verify_symbol_chain (p, n); 82433965Sjdp} 82533965Sjdp 826130561Sobrienstatic void 827130561Sobrienreport_op_error (symbolS *symp, symbolS *left, symbolS *right) 828130561Sobrien{ 829130561Sobrien char *file; 830130561Sobrien unsigned int line; 831130561Sobrien segT seg_left = S_GET_SEGMENT (left); 832130561Sobrien segT seg_right = right ? S_GET_SEGMENT (right) : 0; 833130561Sobrien 834130561Sobrien if (expr_symbol_where (symp, &file, &line)) 835130561Sobrien { 836130561Sobrien if (seg_left == undefined_section) 837130561Sobrien as_bad_where (file, line, 838130561Sobrien _("undefined symbol `%s' in operation"), 839130561Sobrien S_GET_NAME (left)); 840130561Sobrien if (seg_right == undefined_section) 841130561Sobrien as_bad_where (file, line, 842130561Sobrien _("undefined symbol `%s' in operation"), 843130561Sobrien S_GET_NAME (right)); 844130561Sobrien if (seg_left != undefined_section 845130561Sobrien && seg_right != undefined_section) 846130561Sobrien { 847130561Sobrien if (right) 848130561Sobrien as_bad_where (file, line, 849130561Sobrien _("invalid sections for operation on `%s' and `%s'"), 850130561Sobrien S_GET_NAME (left), S_GET_NAME (right)); 851130561Sobrien else 852130561Sobrien as_bad_where (file, line, 853130561Sobrien _("invalid section for operation on `%s'"), 854130561Sobrien S_GET_NAME (left)); 855130561Sobrien } 856130561Sobrien 857130561Sobrien } 858130561Sobrien else 859130561Sobrien { 860130561Sobrien if (seg_left == undefined_section) 861130561Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 862130561Sobrien S_GET_NAME (left), S_GET_NAME (symp)); 863130561Sobrien if (seg_right == undefined_section) 864130561Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 865130561Sobrien S_GET_NAME (right), S_GET_NAME (symp)); 866130561Sobrien if (seg_left != undefined_section 867130561Sobrien && seg_right != undefined_section) 868130561Sobrien { 869130561Sobrien if (right) 870130561Sobrien as_bad_where (file, line, 871130561Sobrien _("invalid sections for operation on `%s' and `%s' setting `%s'"), 872130561Sobrien S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp)); 873130561Sobrien else 874130561Sobrien as_bad_where (file, line, 875130561Sobrien _("invalid section for operation on `%s' setting `%s'"), 876130561Sobrien S_GET_NAME (left), S_GET_NAME (symp)); 877130561Sobrien } 878130561Sobrien } 879130561Sobrien} 880130561Sobrien 88133965Sjdp/* Resolve the value of a symbol. This is called during the final 88233965Sjdp pass over the symbol table to resolve any symbols with complex 88333965Sjdp values. */ 88433965Sjdp 88538889SjdpvalueT 886130561Sobrienresolve_symbol_value (symbolS *symp) 88733965Sjdp{ 88833965Sjdp int resolved; 889104834Sobrien valueT final_val = 0; 89038889Sjdp segT final_seg; 89133965Sjdp 89260484Sobrien#ifdef BFD_ASSEMBLER 89360484Sobrien if (LOCAL_SYMBOL_CHECK (symp)) 89460484Sobrien { 89560484Sobrien struct local_symbol *locsym = (struct local_symbol *) symp; 89660484Sobrien 89789857Sobrien final_val = locsym->lsy_value; 89860484Sobrien if (local_symbol_resolved_p (locsym)) 89989857Sobrien return final_val; 90060484Sobrien 90189857Sobrien final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE; 90260484Sobrien 90389857Sobrien if (finalize_syms) 90460484Sobrien { 90589857Sobrien locsym->lsy_value = final_val; 90660484Sobrien local_symbol_mark_resolved (locsym); 90760484Sobrien } 90860484Sobrien 90960484Sobrien return final_val; 91060484Sobrien } 91160484Sobrien#endif 91260484Sobrien 91333965Sjdp if (symp->sy_resolved) 91438889Sjdp { 91538889Sjdp if (symp->sy_value.X_op == O_constant) 91638889Sjdp return (valueT) symp->sy_value.X_add_number; 91738889Sjdp else 91838889Sjdp return 0; 91938889Sjdp } 92033965Sjdp 92133965Sjdp resolved = 0; 92238889Sjdp final_seg = S_GET_SEGMENT (symp); 92333965Sjdp 92433965Sjdp if (symp->sy_resolving) 92533965Sjdp { 92689857Sobrien if (finalize_syms) 92789857Sobrien as_bad (_("symbol definition loop encountered at `%s'"), 92877298Sobrien S_GET_NAME (symp)); 92938889Sjdp final_val = 0; 93033965Sjdp resolved = 1; 93133965Sjdp } 93233965Sjdp else 93333965Sjdp { 93438889Sjdp symbolS *add_symbol, *op_symbol; 93538889Sjdp offsetT left, right; 93633965Sjdp segT seg_left, seg_right; 93738889Sjdp operatorT op; 93833965Sjdp 93933965Sjdp symp->sy_resolving = 1; 94033965Sjdp 94138889Sjdp /* Help out with CSE. */ 94238889Sjdp add_symbol = symp->sy_value.X_add_symbol; 94338889Sjdp op_symbol = symp->sy_value.X_op_symbol; 94438889Sjdp final_val = symp->sy_value.X_add_number; 94538889Sjdp op = symp->sy_value.X_op; 94638889Sjdp 94738889Sjdp switch (op) 94833965Sjdp { 94938889Sjdp default: 95038889Sjdp BAD_CASE (op); 95138889Sjdp break; 95233965Sjdp 95333965Sjdp case O_absent: 95438889Sjdp final_val = 0; 95533965Sjdp /* Fall through. */ 95638889Sjdp 95733965Sjdp case O_constant: 95860484Sobrien final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; 95938889Sjdp if (final_seg == expr_section) 96038889Sjdp final_seg = absolute_section; 96133965Sjdp resolved = 1; 96233965Sjdp break; 96333965Sjdp 96433965Sjdp case O_symbol: 96538889Sjdp case O_symbol_rva: 96689857Sobrien left = resolve_symbol_value (add_symbol); 96789857Sobrien seg_left = S_GET_SEGMENT (add_symbol); 96889857Sobrien if (finalize_syms) 96989857Sobrien symp->sy_value.X_op_symbol = NULL; 97089857Sobrien 97138889Sjdp do_symbol: 97233965Sjdp if (symp->sy_mri_common) 97333965Sjdp { 97433965Sjdp /* This is a symbol inside an MRI common section. The 97589857Sobrien relocation routines are going to handle it specially. 97689857Sobrien Don't change the value. */ 97760484Sobrien resolved = symbol_resolved_p (add_symbol); 97833965Sjdp break; 97933965Sjdp } 98033965Sjdp 98189857Sobrien if (finalize_syms && final_val == 0) 98260484Sobrien { 98360484Sobrien if (LOCAL_SYMBOL_CHECK (add_symbol)) 98460484Sobrien add_symbol = local_symbol_convert ((struct local_symbol *) 98560484Sobrien add_symbol); 98660484Sobrien copy_symbol_attributes (symp, add_symbol); 98760484Sobrien } 98833965Sjdp 98989857Sobrien /* If we have equated this symbol to an undefined or common 99089857Sobrien symbol, keep X_op set to O_symbol, and don't change 99189857Sobrien X_add_number. This permits the routine which writes out 99289857Sobrien relocation to detect this case, and convert the 99389857Sobrien relocation to be against the symbol to which this symbol 99489857Sobrien is equated. */ 99538889Sjdp if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol)) 99633965Sjdp { 99789857Sobrien if (finalize_syms) 99838889Sjdp { 99938889Sjdp symp->sy_value.X_op = O_symbol; 100060484Sobrien symp->sy_value.X_add_symbol = add_symbol; 100138889Sjdp symp->sy_value.X_add_number = final_val; 100289857Sobrien /* Use X_op_symbol as a flag. */ 100389857Sobrien symp->sy_value.X_op_symbol = add_symbol; 100489857Sobrien final_seg = seg_left; 100538889Sjdp } 100638889Sjdp final_val = 0; 100760484Sobrien resolved = symbol_resolved_p (add_symbol); 100889857Sobrien symp->sy_resolving = 0; 100938889Sjdp goto exit_dont_set_value; 101033965Sjdp } 101189857Sobrien else if (finalize_syms && final_seg == expr_section 101289857Sobrien && seg_left != expr_section) 101389857Sobrien { 101489857Sobrien /* If the symbol is an expression symbol, do similarly 101589857Sobrien as for undefined and common syms above. Handles 101689857Sobrien "sym +/- expr" where "expr" cannot be evaluated 101789857Sobrien immediately, and we want relocations to be against 101889857Sobrien "sym", eg. because it is weak. */ 101989857Sobrien symp->sy_value.X_op = O_symbol; 102089857Sobrien symp->sy_value.X_add_symbol = add_symbol; 102189857Sobrien symp->sy_value.X_add_number = final_val; 102289857Sobrien symp->sy_value.X_op_symbol = add_symbol; 102389857Sobrien final_seg = seg_left; 102489857Sobrien final_val += symp->sy_frag->fr_address + left; 102589857Sobrien resolved = symbol_resolved_p (add_symbol); 102689857Sobrien symp->sy_resolving = 0; 102789857Sobrien goto exit_dont_set_value; 102889857Sobrien } 102933965Sjdp else 103033965Sjdp { 103138889Sjdp final_val += symp->sy_frag->fr_address + left; 103238889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 103389857Sobrien final_seg = seg_left; 103433965Sjdp } 103533965Sjdp 103660484Sobrien resolved = symbol_resolved_p (add_symbol); 103733965Sjdp break; 103833965Sjdp 103933965Sjdp case O_uminus: 104033965Sjdp case O_bit_not: 104133965Sjdp case O_logical_not: 104289857Sobrien left = resolve_symbol_value (add_symbol); 104399461Sobrien seg_left = S_GET_SEGMENT (add_symbol); 104438889Sjdp 1045130561Sobrien /* By reducing these to the relevant dyadic operator, we get 1046130561Sobrien !S -> S == 0 permitted on anything, 1047130561Sobrien -S -> 0 - S only permitted on absolute 1048130561Sobrien ~S -> S ^ ~0 only permitted on absolute */ 1049130561Sobrien if (op != O_logical_not && seg_left != absolute_section 1050130561Sobrien && finalize_syms) 1051130561Sobrien report_op_error (symp, add_symbol, NULL); 1052130561Sobrien 1053130561Sobrien if (final_seg == expr_section || final_seg == undefined_section) 1054130561Sobrien final_seg = absolute_section; 1055130561Sobrien 105638889Sjdp if (op == O_uminus) 105738889Sjdp left = -left; 105838889Sjdp else if (op == O_logical_not) 105938889Sjdp left = !left; 106033965Sjdp else 106138889Sjdp left = ~left; 106238889Sjdp 106338889Sjdp final_val += left + symp->sy_frag->fr_address; 106438889Sjdp 106560484Sobrien resolved = symbol_resolved_p (add_symbol); 106633965Sjdp break; 106733965Sjdp 106833965Sjdp case O_multiply: 106933965Sjdp case O_divide: 107033965Sjdp case O_modulus: 107133965Sjdp case O_left_shift: 107233965Sjdp case O_right_shift: 107333965Sjdp case O_bit_inclusive_or: 107433965Sjdp case O_bit_or_not: 107533965Sjdp case O_bit_exclusive_or: 107633965Sjdp case O_bit_and: 107733965Sjdp case O_add: 107833965Sjdp case O_subtract: 107933965Sjdp case O_eq: 108033965Sjdp case O_ne: 108133965Sjdp case O_lt: 108233965Sjdp case O_le: 108333965Sjdp case O_ge: 108433965Sjdp case O_gt: 108533965Sjdp case O_logical_and: 108633965Sjdp case O_logical_or: 108789857Sobrien left = resolve_symbol_value (add_symbol); 108889857Sobrien right = resolve_symbol_value (op_symbol); 108938889Sjdp seg_left = S_GET_SEGMENT (add_symbol); 109038889Sjdp seg_right = S_GET_SEGMENT (op_symbol); 109133965Sjdp 109238889Sjdp /* Simplify addition or subtraction of a constant by folding the 109338889Sjdp constant into X_add_number. */ 109489857Sobrien if (op == O_add) 109538889Sjdp { 109638889Sjdp if (seg_right == absolute_section) 109738889Sjdp { 109889857Sobrien final_val += right; 109938889Sjdp goto do_symbol; 110038889Sjdp } 110189857Sobrien else if (seg_left == absolute_section) 110238889Sjdp { 110338889Sjdp final_val += left; 110438889Sjdp add_symbol = op_symbol; 110538889Sjdp left = right; 110689857Sobrien seg_left = seg_right; 110738889Sjdp goto do_symbol; 110838889Sjdp } 110938889Sjdp } 111089857Sobrien else if (op == O_subtract) 111189857Sobrien { 111289857Sobrien if (seg_right == absolute_section) 111389857Sobrien { 111489857Sobrien final_val -= right; 111589857Sobrien goto do_symbol; 111689857Sobrien } 111789857Sobrien } 111838889Sjdp 111989857Sobrien /* Equality and non-equality tests are permitted on anything. 112089857Sobrien Subtraction, and other comparison operators are permitted if 112189857Sobrien both operands are in the same section. Otherwise, both 112289857Sobrien operands must be absolute. We already handled the case of 112389857Sobrien addition or subtraction of a constant above. This will 112489857Sobrien probably need to be changed for an object file format which 112589857Sobrien supports arbitrary expressions, such as IEEE-695. 112689857Sobrien 112789857Sobrien Don't emit messages unless we're finalizing the symbol value, 112838889Sjdp otherwise we may get the same message multiple times. */ 1129130561Sobrien if (finalize_syms 1130130561Sobrien && !(seg_left == absolute_section 1131130561Sobrien && seg_right == absolute_section) 1132130561Sobrien && !(op == O_eq || op == O_ne) 1133130561Sobrien && !((op == O_subtract 1134130561Sobrien || op == O_lt || op == O_le || op == O_ge || op == O_gt) 1135130561Sobrien && seg_left == seg_right 1136130561Sobrien && (seg_left != undefined_section 1137130561Sobrien || add_symbol == op_symbol))) 1138130561Sobrien report_op_error (symp, add_symbol, op_symbol); 113933965Sjdp 1140130561Sobrien if (final_seg == expr_section || final_seg == undefined_section) 1141130561Sobrien final_seg = absolute_section; 114233965Sjdp 114338889Sjdp /* Check for division by zero. */ 114438889Sjdp if ((op == O_divide || op == O_modulus) && right == 0) 114538889Sjdp { 114638889Sjdp /* If seg_right is not absolute_section, then we've 114789857Sobrien already issued a warning about using a bad symbol. */ 114889857Sobrien if (seg_right == absolute_section && finalize_syms) 114938889Sjdp { 115038889Sjdp char *file; 115138889Sjdp unsigned int line; 115238889Sjdp 115338889Sjdp if (expr_symbol_where (symp, &file, &line)) 115460484Sobrien as_bad_where (file, line, _("division by zero")); 115538889Sjdp else 115689857Sobrien as_bad (_("division by zero when setting `%s'"), 115738889Sjdp S_GET_NAME (symp)); 115838889Sjdp } 115938889Sjdp 116038889Sjdp right = 1; 116138889Sjdp } 116238889Sjdp 116333965Sjdp switch (symp->sy_value.X_op) 116433965Sjdp { 116538889Sjdp case O_multiply: left *= right; break; 116638889Sjdp case O_divide: left /= right; break; 116738889Sjdp case O_modulus: left %= right; break; 116838889Sjdp case O_left_shift: left <<= right; break; 116938889Sjdp case O_right_shift: left >>= right; break; 117038889Sjdp case O_bit_inclusive_or: left |= right; break; 117138889Sjdp case O_bit_or_not: left |= ~right; break; 117238889Sjdp case O_bit_exclusive_or: left ^= right; break; 117338889Sjdp case O_bit_and: left &= right; break; 117438889Sjdp case O_add: left += right; break; 117538889Sjdp case O_subtract: left -= right; break; 117689857Sobrien case O_eq: 117789857Sobrien case O_ne: 117889857Sobrien left = (left == right && seg_left == seg_right 117989857Sobrien && (seg_left != undefined_section 118089857Sobrien || add_symbol == op_symbol) 118189857Sobrien ? ~ (offsetT) 0 : 0); 118289857Sobrien if (symp->sy_value.X_op == O_ne) 118389857Sobrien left = ~left; 118489857Sobrien break; 118538889Sjdp case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; 118638889Sjdp case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; 118738889Sjdp case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; 118838889Sjdp case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; 118938889Sjdp case O_logical_and: left = left && right; break; 119038889Sjdp case O_logical_or: left = left || right; break; 119138889Sjdp default: abort (); 119233965Sjdp } 119338889Sjdp 119438889Sjdp final_val += symp->sy_frag->fr_address + left; 119538889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 119699461Sobrien { 119799461Sobrien if (seg_left == undefined_section 119899461Sobrien || seg_right == undefined_section) 119999461Sobrien final_seg = undefined_section; 120099461Sobrien else if (seg_left == absolute_section) 120199461Sobrien final_seg = seg_right; 120299461Sobrien else 120399461Sobrien final_seg = seg_left; 120499461Sobrien } 120560484Sobrien resolved = (symbol_resolved_p (add_symbol) 120660484Sobrien && symbol_resolved_p (op_symbol)); 120777298Sobrien break; 120833965Sjdp 120933965Sjdp case O_register: 121033965Sjdp case O_big: 121133965Sjdp case O_illegal: 121233965Sjdp /* Give an error (below) if not in expr_section. We don't 121333965Sjdp want to worry about expr_section symbols, because they 121433965Sjdp are fictional (they are created as part of expression 121533965Sjdp resolution), and any problems may not actually mean 121633965Sjdp anything. */ 121733965Sjdp break; 121833965Sjdp } 121938889Sjdp 122038889Sjdp symp->sy_resolving = 0; 122133965Sjdp } 122233965Sjdp 122389857Sobrien if (finalize_syms) 122489857Sobrien S_SET_VALUE (symp, final_val); 122538889Sjdp 122689857Sobrienexit_dont_set_value: 122789857Sobrien /* Always set the segment, even if not finalizing the value. 122889857Sobrien The segment is used to determine whether a symbol is defined. */ 122938889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER) 123089857Sobrien /* The old a.out backend does not handle S_SET_SEGMENT correctly 123189857Sobrien for a stab symbol, so we use this bad hack. */ 123289857Sobrien if (final_seg != S_GET_SEGMENT (symp)) 123338889Sjdp#endif 123489857Sobrien S_SET_SEGMENT (symp, final_seg); 123538889Sjdp 123633965Sjdp /* Don't worry if we can't resolve an expr_section symbol. */ 123789857Sobrien if (finalize_syms) 123833965Sjdp { 123938889Sjdp if (resolved) 124038889Sjdp symp->sy_resolved = 1; 124138889Sjdp else if (S_GET_SEGMENT (symp) != expr_section) 124238889Sjdp { 124389857Sobrien as_bad (_("can't resolve value for symbol `%s'"), 124477298Sobrien S_GET_NAME (symp)); 124538889Sjdp symp->sy_resolved = 1; 124638889Sjdp } 124733965Sjdp } 124838889Sjdp 124938889Sjdp return final_val; 125033965Sjdp} 125133965Sjdp 125260484Sobrien#ifdef BFD_ASSEMBLER 125360484Sobrien 1254130561Sobrienstatic void resolve_local_symbol (const char *, PTR); 125560484Sobrien 125660484Sobrien/* A static function passed to hash_traverse. */ 125760484Sobrien 125860484Sobrienstatic void 1259130561Sobrienresolve_local_symbol (const char *key ATTRIBUTE_UNUSED, PTR value) 126060484Sobrien{ 126160484Sobrien if (value != NULL) 126289857Sobrien resolve_symbol_value (value); 126360484Sobrien} 126460484Sobrien 126560484Sobrien#endif 126660484Sobrien 126760484Sobrien/* Resolve all local symbols. */ 126860484Sobrien 126960484Sobrienvoid 1270130561Sobrienresolve_local_symbol_values (void) 127160484Sobrien{ 127260484Sobrien#ifdef BFD_ASSEMBLER 127360484Sobrien hash_traverse (local_hash, resolve_local_symbol); 127460484Sobrien#endif 127560484Sobrien} 127660484Sobrien 127733965Sjdp/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". 127833965Sjdp They are *really* local. That is, they go out of scope whenever we see a 127933965Sjdp label that isn't local. Also, like fb labels, there can be multiple 128033965Sjdp instances of a dollar label. Therefor, we name encode each instance with 128133965Sjdp the instance number, keep a list of defined symbols separate from the real 128233965Sjdp symbol table, and we treat these buggers as a sparse array. */ 128333965Sjdp 128433965Sjdpstatic long *dollar_labels; 128533965Sjdpstatic long *dollar_label_instances; 128633965Sjdpstatic char *dollar_label_defines; 128738889Sjdpstatic unsigned long dollar_label_count; 128833965Sjdpstatic unsigned long dollar_label_max; 128933965Sjdp 129077298Sobrienint 1291130561Sobriendollar_label_defined (long label) 129233965Sjdp{ 129333965Sjdp long *i; 129433965Sjdp 129533965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 129633965Sjdp 129733965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 129833965Sjdp if (*i == label) 129933965Sjdp return dollar_label_defines[i - dollar_labels]; 130033965Sjdp 130177298Sobrien /* If we get here, label isn't defined. */ 130233965Sjdp return 0; 130377298Sobrien} 130433965Sjdp 130533965Sjdpstatic long 1306130561Sobriendollar_label_instance (long label) 130733965Sjdp{ 130833965Sjdp long *i; 130933965Sjdp 131033965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 131133965Sjdp 131233965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 131333965Sjdp if (*i == label) 131433965Sjdp return (dollar_label_instances[i - dollar_labels]); 131533965Sjdp 131677298Sobrien /* If we get here, we haven't seen the label before. 131777298Sobrien Therefore its instance count is zero. */ 131833965Sjdp return 0; 131933965Sjdp} 132033965Sjdp 132177298Sobrienvoid 1322130561Sobriendollar_label_clear (void) 132333965Sjdp{ 132433965Sjdp memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count); 132533965Sjdp} 132633965Sjdp 132733965Sjdp#define DOLLAR_LABEL_BUMP_BY 10 132833965Sjdp 132977298Sobrienvoid 1330130561Sobriendefine_dollar_label (long label) 133133965Sjdp{ 133233965Sjdp long *i; 133333965Sjdp 133433965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 133533965Sjdp if (*i == label) 133633965Sjdp { 133733965Sjdp ++dollar_label_instances[i - dollar_labels]; 133833965Sjdp dollar_label_defines[i - dollar_labels] = 1; 133933965Sjdp return; 134033965Sjdp } 134133965Sjdp 134277298Sobrien /* If we get to here, we don't have label listed yet. */ 134333965Sjdp 134433965Sjdp if (dollar_labels == NULL) 134533965Sjdp { 134633965Sjdp dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 134733965Sjdp dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 134833965Sjdp dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY); 134933965Sjdp dollar_label_max = DOLLAR_LABEL_BUMP_BY; 135033965Sjdp dollar_label_count = 0; 135133965Sjdp } 135233965Sjdp else if (dollar_label_count == dollar_label_max) 135333965Sjdp { 135433965Sjdp dollar_label_max += DOLLAR_LABEL_BUMP_BY; 135533965Sjdp dollar_labels = (long *) xrealloc ((char *) dollar_labels, 135633965Sjdp dollar_label_max * sizeof (long)); 135733965Sjdp dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances, 135833965Sjdp dollar_label_max * sizeof (long)); 135933965Sjdp dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max); 136077298Sobrien } /* if we needed to grow */ 136133965Sjdp 136233965Sjdp dollar_labels[dollar_label_count] = label; 136333965Sjdp dollar_label_instances[dollar_label_count] = 1; 136433965Sjdp dollar_label_defines[dollar_label_count] = 1; 136533965Sjdp ++dollar_label_count; 136633965Sjdp} 136733965Sjdp 136877298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 136933965Sjdp 137077298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Am" 137177298Sobrien where n is the label number and m is the instance number. "L" makes 137277298Sobrien it a label discarded unless debugging and "^A"('\1') ensures no 137377298Sobrien ordinary symbol SHOULD get the same name as a local label 137477298Sobrien symbol. The first "4:" is "L4^A1" - the m numbers begin at 1. 137577298Sobrien 137677298Sobrien fb labels get the same treatment, except that ^B is used in place 137777298Sobrien of ^A. */ 137877298Sobrien 137977298Sobrienchar * /* Return local label name. */ 1380130561Sobriendollar_label_name (register long n, /* we just saw "n$:" : n a number. */ 1381130561Sobrien register int augend /* 0 for current instance, 1 for new instance. */) 138233965Sjdp{ 138333965Sjdp long i; 138477298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 138533965Sjdp static char symbol_name_build[24]; 138633965Sjdp register char *p; 138733965Sjdp register char *q; 138877298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 138933965Sjdp 139033965Sjdp know (n >= 0); 139133965Sjdp know (augend == 0 || augend == 1); 139233965Sjdp p = symbol_name_build; 139360484Sobrien#ifdef LOCAL_LABEL_PREFIX 139460484Sobrien *p++ = LOCAL_LABEL_PREFIX; 139560484Sobrien#endif 139633965Sjdp *p++ = 'L'; 139733965Sjdp 139877298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 139977298Sobrien /* Label number. */ 140033965Sjdp q = symbol_name_temporary; 140133965Sjdp for (*q++ = 0, i = n; i; ++q) 140233965Sjdp { 140333965Sjdp *q = i % 10 + '0'; 140433965Sjdp i /= 10; 140533965Sjdp } 140633965Sjdp while ((*p = *--q) != '\0') 140733965Sjdp ++p; 140833965Sjdp 140977298Sobrien *p++ = DOLLAR_LABEL_CHAR; /* ^A */ 141033965Sjdp 141177298Sobrien /* Instance number. */ 141233965Sjdp q = symbol_name_temporary; 141333965Sjdp for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q) 141433965Sjdp { 141533965Sjdp *q = i % 10 + '0'; 141633965Sjdp i /= 10; 141733965Sjdp } 141833965Sjdp while ((*p++ = *--q) != '\0');; 141933965Sjdp 142077298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 142133965Sjdp return symbol_name_build; 142233965Sjdp} 142333965Sjdp 1424130561Sobrien/* Somebody else's idea of local labels. They are made by "n:" where n 142577298Sobrien is any decimal digit. Refer to them with 142677298Sobrien "nb" for previous (backward) n: 142777298Sobrien or "nf" for next (forward) n:. 142833965Sjdp 142977298Sobrien We do a little better and let n be any number, not just a single digit, but 143077298Sobrien since the other guy's assembler only does ten, we treat the first ten 143177298Sobrien specially. 143277298Sobrien 143377298Sobrien Like someone else's assembler, we have one set of local label counters for 143477298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 143577298Sobrien implies that one can refer to a label in another segment, and indeed some 143677298Sobrien crufty compilers have done just that. 143777298Sobrien 143877298Sobrien Since there could be a LOT of these things, treat them as a sparse 143977298Sobrien array. */ 144077298Sobrien 144133965Sjdp#define FB_LABEL_SPECIAL (10) 144233965Sjdp 144333965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 144433965Sjdpstatic long *fb_labels; 144533965Sjdpstatic long *fb_label_instances; 144633965Sjdpstatic long fb_label_count; 144733965Sjdpstatic long fb_label_max; 144833965Sjdp 144977298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 145033965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 145133965Sjdp 145277298Sobrienstatic void 1453130561Sobrienfb_label_init (void) 145433965Sjdp{ 145533965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 145677298Sobrien} 145733965Sjdp 145877298Sobrien/* Add one to the instance number of this fb label. */ 145977298Sobrien 146077298Sobrienvoid 1461130561Sobrienfb_label_instance_inc (long label) 146233965Sjdp{ 146333965Sjdp long *i; 146433965Sjdp 146533965Sjdp if (label < FB_LABEL_SPECIAL) 146633965Sjdp { 146733965Sjdp ++fb_low_counter[label]; 146833965Sjdp return; 146933965Sjdp } 147033965Sjdp 147133965Sjdp if (fb_labels != NULL) 147233965Sjdp { 147333965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 147433965Sjdp i < fb_labels + fb_label_count; ++i) 147533965Sjdp { 147633965Sjdp if (*i == label) 147733965Sjdp { 147833965Sjdp ++fb_label_instances[i - fb_labels]; 147933965Sjdp return; 148077298Sobrien } /* if we find it */ 148177298Sobrien } /* for each existing label */ 148233965Sjdp } 148333965Sjdp 148477298Sobrien /* If we get to here, we don't have label listed yet. */ 148533965Sjdp 148633965Sjdp if (fb_labels == NULL) 148733965Sjdp { 148833965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 148933965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 149033965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 149133965Sjdp fb_label_count = FB_LABEL_SPECIAL; 149233965Sjdp 149333965Sjdp } 149433965Sjdp else if (fb_label_count == fb_label_max) 149533965Sjdp { 149633965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 149733965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 149833965Sjdp fb_label_max * sizeof (long)); 149933965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 150033965Sjdp fb_label_max * sizeof (long)); 150177298Sobrien } /* if we needed to grow */ 150233965Sjdp 150333965Sjdp fb_labels[fb_label_count] = label; 150433965Sjdp fb_label_instances[fb_label_count] = 1; 150533965Sjdp ++fb_label_count; 150633965Sjdp} 150733965Sjdp 150877298Sobrienstatic long 1509130561Sobrienfb_label_instance (long label) 151033965Sjdp{ 151133965Sjdp long *i; 151233965Sjdp 151333965Sjdp if (label < FB_LABEL_SPECIAL) 151433965Sjdp { 151533965Sjdp return (fb_low_counter[label]); 151633965Sjdp } 151733965Sjdp 151833965Sjdp if (fb_labels != NULL) 151933965Sjdp { 152033965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 152133965Sjdp i < fb_labels + fb_label_count; ++i) 152233965Sjdp { 152333965Sjdp if (*i == label) 152433965Sjdp { 152533965Sjdp return (fb_label_instances[i - fb_labels]); 152677298Sobrien } /* if we find it */ 152777298Sobrien } /* for each existing label */ 152833965Sjdp } 152933965Sjdp 153033965Sjdp /* We didn't find the label, so this must be a reference to the 153133965Sjdp first instance. */ 153233965Sjdp return 0; 153333965Sjdp} 153433965Sjdp 153577298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 153633965Sjdp 153777298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 153877298Sobrien where n is the label number and m is the instance number. "L" makes 153977298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 154077298Sobrien ordinary symbol SHOULD get the same name as a local label 154177298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 154277298Sobrien 154377298Sobrien dollar labels get the same treatment, except that ^A is used in 154477298Sobrien place of ^B. */ 154577298Sobrien 154677298Sobrienchar * /* Return local label name. */ 1547130561Sobrienfb_label_name (long n, /* We just saw "n:", "nf" or "nb" : n a number. */ 1548130561Sobrien long augend /* 0 for nb, 1 for n:, nf. */) 154933965Sjdp{ 155033965Sjdp long i; 155177298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 155233965Sjdp static char symbol_name_build[24]; 155333965Sjdp register char *p; 155433965Sjdp register char *q; 155577298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 155633965Sjdp 155733965Sjdp know (n >= 0); 155833965Sjdp know (augend == 0 || augend == 1); 155933965Sjdp p = symbol_name_build; 156077298Sobrien#ifdef LOCAL_LABEL_PREFIX 156177298Sobrien *p++ = LOCAL_LABEL_PREFIX; 156277298Sobrien#endif 156333965Sjdp *p++ = 'L'; 156433965Sjdp 156577298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 156677298Sobrien /* Label number. */ 156733965Sjdp q = symbol_name_temporary; 156833965Sjdp for (*q++ = 0, i = n; i; ++q) 156933965Sjdp { 157033965Sjdp *q = i % 10 + '0'; 157133965Sjdp i /= 10; 157233965Sjdp } 157333965Sjdp while ((*p = *--q) != '\0') 157433965Sjdp ++p; 157533965Sjdp 157677298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 157733965Sjdp 157877298Sobrien /* Instance number. */ 157933965Sjdp q = symbol_name_temporary; 158033965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 158133965Sjdp { 158233965Sjdp *q = i % 10 + '0'; 158333965Sjdp i /= 10; 158433965Sjdp } 158533965Sjdp while ((*p++ = *--q) != '\0');; 158633965Sjdp 158777298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 158833965Sjdp return (symbol_name_build); 158977298Sobrien} 159033965Sjdp 159177298Sobrien/* Decode name that may have been generated by foo_label_name() above. 159277298Sobrien If the name wasn't generated by foo_label_name(), then return it 159377298Sobrien unaltered. This is used for error messages. */ 159433965Sjdp 159533965Sjdpchar * 1596130561Sobriendecode_local_label_name (char *s) 159733965Sjdp{ 159833965Sjdp char *p; 159933965Sjdp char *symbol_decode; 160033965Sjdp int label_number; 160133965Sjdp int instance_number; 160233965Sjdp char *type; 160378828Sobrien const char *message_format; 160477298Sobrien int index = 0; 160533965Sjdp 160677298Sobrien#ifdef LOCAL_LABEL_PREFIX 160777298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 160877298Sobrien ++index; 160977298Sobrien#endif 161077298Sobrien 161177298Sobrien if (s[index] != 'L') 161233965Sjdp return s; 161333965Sjdp 161489857Sobrien for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p) 161533965Sjdp label_number = (10 * label_number) + *p - '0'; 161633965Sjdp 161777298Sobrien if (*p == DOLLAR_LABEL_CHAR) 161833965Sjdp type = "dollar"; 161977298Sobrien else if (*p == LOCAL_LABEL_CHAR) 162033965Sjdp type = "fb"; 162133965Sjdp else 162233965Sjdp return s; 162333965Sjdp 162489857Sobrien for (instance_number = 0, p++; ISDIGIT (*p); ++p) 162533965Sjdp instance_number = (10 * instance_number) + *p - '0'; 162633965Sjdp 162778828Sobrien message_format = _("\"%d\" (instance number %d of a %s label)"); 162833965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 162933965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 163033965Sjdp 163133965Sjdp return symbol_decode; 163233965Sjdp} 163333965Sjdp 163433965Sjdp/* Get the value of a symbol. */ 163533965Sjdp 163633965SjdpvalueT 1637130561SobrienS_GET_VALUE (symbolS *s) 163833965Sjdp{ 163960484Sobrien#ifdef BFD_ASSEMBLER 164060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 164189857Sobrien return resolve_symbol_value (s); 164260484Sobrien#endif 164360484Sobrien 164489857Sobrien if (!s->sy_resolved) 164589857Sobrien { 164689857Sobrien valueT val = resolve_symbol_value (s); 164789857Sobrien if (!finalize_syms) 164889857Sobrien return val; 164989857Sobrien } 165033965Sjdp if (s->sy_value.X_op != O_constant) 165133965Sjdp { 165233965Sjdp static symbolS *recur; 165333965Sjdp 165433965Sjdp /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON 1655130561Sobrien may call S_GET_VALUE. We use a static symbol to avoid the 1656130561Sobrien immediate recursion. */ 165733965Sjdp if (recur == s) 165833965Sjdp return (valueT) s->sy_value.X_add_number; 165933965Sjdp recur = s; 166033965Sjdp if (! s->sy_resolved 166133965Sjdp || s->sy_value.X_op != O_symbol 166233965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 166389857Sobrien as_bad (_("attempt to get value of unresolved symbol `%s'"), 166433965Sjdp S_GET_NAME (s)); 166533965Sjdp recur = NULL; 166633965Sjdp } 166733965Sjdp return (valueT) s->sy_value.X_add_number; 166833965Sjdp} 166933965Sjdp 167033965Sjdp/* Set the value of a symbol. */ 167133965Sjdp 167233965Sjdpvoid 1673130561SobrienS_SET_VALUE (symbolS *s, valueT val) 167433965Sjdp{ 167560484Sobrien#ifdef BFD_ASSEMBLER 167660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 167760484Sobrien { 167889857Sobrien ((struct local_symbol *) s)->lsy_value = val; 167960484Sobrien return; 168060484Sobrien } 168160484Sobrien#endif 168260484Sobrien 168333965Sjdp s->sy_value.X_op = O_constant; 168433965Sjdp s->sy_value.X_add_number = (offsetT) val; 168533965Sjdp s->sy_value.X_unsigned = 0; 168633965Sjdp} 168733965Sjdp 168833965Sjdpvoid 1689130561Sobriencopy_symbol_attributes (symbolS *dest, symbolS *src) 169033965Sjdp{ 169160484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 169260484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 169360484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 169460484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 169560484Sobrien 169633965Sjdp#ifdef BFD_ASSEMBLER 169733965Sjdp /* In an expression, transfer the settings of these flags. 169833965Sjdp The user can override later, of course. */ 169938889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 170033965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 170133965Sjdp#endif 170233965Sjdp 170333965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 170433965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 170533965Sjdp#endif 170633965Sjdp} 170733965Sjdp 170833965Sjdp#ifdef BFD_ASSEMBLER 170933965Sjdp 171033965Sjdpint 1711130561SobrienS_IS_FUNCTION (symbolS *s) 171260484Sobrien{ 171360484Sobrien flagword flags; 171460484Sobrien 171560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 171660484Sobrien return 0; 171760484Sobrien 171860484Sobrien flags = s->bsym->flags; 171960484Sobrien 172060484Sobrien return (flags & BSF_FUNCTION) != 0; 172160484Sobrien} 172260484Sobrien 172360484Sobrienint 1724130561SobrienS_IS_EXTERNAL (symbolS *s) 172533965Sjdp{ 172660484Sobrien flagword flags; 172733965Sjdp 172860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 172960484Sobrien return 0; 173060484Sobrien 173160484Sobrien flags = s->bsym->flags; 173260484Sobrien 173377298Sobrien /* Sanity check. */ 173438889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 173533965Sjdp abort (); 173633965Sjdp 173733965Sjdp return (flags & BSF_GLOBAL) != 0; 173833965Sjdp} 173933965Sjdp 174033965Sjdpint 1741130561SobrienS_IS_WEAK (symbolS *s) 174233965Sjdp{ 174360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 174460484Sobrien return 0; 174533965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 174633965Sjdp} 174733965Sjdp 174833965Sjdpint 1749130561SobrienS_IS_COMMON (symbolS *s) 175033965Sjdp{ 175160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 175260484Sobrien return 0; 175333965Sjdp return bfd_is_com_section (s->bsym->section); 175433965Sjdp} 175533965Sjdp 175633965Sjdpint 1757130561SobrienS_IS_DEFINED (symbolS *s) 175833965Sjdp{ 175960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 176060484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 176133965Sjdp return s->bsym->section != undefined_section; 176233965Sjdp} 176333965Sjdp 1764130561Sobrien 1765130561Sobrien#ifndef EXTERN_FORCE_RELOC 1766130561Sobrien#define EXTERN_FORCE_RELOC IS_ELF 1767130561Sobrien#endif 1768130561Sobrien 1769130561Sobrien/* Return true for symbols that should not be reduced to section 1770130561Sobrien symbols or eliminated from expressions, because they may be 1771130561Sobrien overridden by the linker. */ 177233965Sjdpint 1773130561SobrienS_FORCE_RELOC (symbolS *s, int strict) 177433965Sjdp{ 177560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 1776130561Sobrien return ((struct local_symbol *) s)->lsy_section == undefined_section; 1777130561Sobrien 1778130561Sobrien return ((strict 1779130561Sobrien && ((s->bsym->flags & BSF_WEAK) != 0 1780130561Sobrien || (EXTERN_FORCE_RELOC 1781130561Sobrien && (s->bsym->flags & BSF_GLOBAL) != 0))) 1782130561Sobrien || s->bsym->section == undefined_section 1783130561Sobrien || bfd_is_com_section (s->bsym->section)); 1784130561Sobrien} 1785130561Sobrien 1786130561Sobrienint 1787130561SobrienS_IS_DEBUG (symbolS *s) 1788130561Sobrien{ 1789130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 179060484Sobrien return 0; 179133965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 179233965Sjdp return 1; 179333965Sjdp return 0; 179433965Sjdp} 179533965Sjdp 179633965Sjdpint 1797130561SobrienS_IS_LOCAL (symbolS *s) 179833965Sjdp{ 179960484Sobrien flagword flags; 180033965Sjdp const char *name; 180133965Sjdp 180260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 180360484Sobrien return 1; 180460484Sobrien 180560484Sobrien flags = s->bsym->flags; 180660484Sobrien 180777298Sobrien /* Sanity check. */ 180838889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 180933965Sjdp abort (); 181033965Sjdp 181133965Sjdp if (bfd_get_section (s->bsym) == reg_section) 181233965Sjdp return 1; 181333965Sjdp 181438889Sjdp if (flag_strip_local_absolute 181538889Sjdp && (flags & BSF_GLOBAL) == 0 181638889Sjdp && bfd_get_section (s->bsym) == absolute_section) 181738889Sjdp return 1; 181838889Sjdp 181933965Sjdp name = S_GET_NAME (s); 182033965Sjdp return (name != NULL 182133965Sjdp && ! S_IS_DEBUG (s) 182277298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 182377298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 182433965Sjdp || (! flag_keep_locals 182533965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 182633965Sjdp || (flag_mri 182733965Sjdp && name[0] == '?' 182833965Sjdp && name[1] == '?'))))); 182933965Sjdp} 183033965Sjdp 183133965Sjdpint 1832130561SobrienS_IS_EXTERN (symbolS *s) 183333965Sjdp{ 183433965Sjdp return S_IS_EXTERNAL (s); 183533965Sjdp} 183633965Sjdp 183733965Sjdpint 1838130561SobrienS_IS_STABD (symbolS *s) 183933965Sjdp{ 184033965Sjdp return S_GET_NAME (s) == 0; 184133965Sjdp} 184233965Sjdp 1843104834Sobrienconst char * 1844130561SobrienS_GET_NAME (symbolS *s) 184533965Sjdp{ 184660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 184760484Sobrien return ((struct local_symbol *) s)->lsy_name; 184833965Sjdp return s->bsym->name; 184933965Sjdp} 185033965Sjdp 185133965SjdpsegT 1852130561SobrienS_GET_SEGMENT (symbolS *s) 185333965Sjdp{ 185460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 185560484Sobrien return ((struct local_symbol *) s)->lsy_section; 185633965Sjdp return s->bsym->section; 185733965Sjdp} 185833965Sjdp 185933965Sjdpvoid 1860130561SobrienS_SET_SEGMENT (symbolS *s, segT seg) 186133965Sjdp{ 186238889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 186338889Sjdp faults assigning back to const global symbols such as *ABS*, but it 186438889Sjdp shouldn't happen anyway. */ 186538889Sjdp 186660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 186760484Sobrien { 186860484Sobrien if (seg == reg_section) 186960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 187060484Sobrien else 187160484Sobrien { 187260484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 187360484Sobrien return; 187460484Sobrien } 187560484Sobrien } 187660484Sobrien 187738889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 187838889Sjdp { 187938889Sjdp if (s->bsym->section != seg) 188077298Sobrien abort (); 188138889Sjdp } 188238889Sjdp else 188338889Sjdp s->bsym->section = seg; 188433965Sjdp} 188533965Sjdp 188633965Sjdpvoid 1887130561SobrienS_SET_EXTERNAL (symbolS *s) 188833965Sjdp{ 188960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 189060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 189133965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 189233965Sjdp { 189333965Sjdp /* Let .weak override .global. */ 189433965Sjdp return; 189533965Sjdp } 189678828Sobrien if (s->bsym->flags & BSF_SECTION_SYM) 189778828Sobrien { 189878828Sobrien char * file; 189978828Sobrien unsigned int line; 1900104834Sobrien 190178828Sobrien /* Do not reassign section symbols. */ 190278828Sobrien as_where (& file, & line); 190378828Sobrien as_warn_where (file, line, 190489857Sobrien _("section symbols are already global")); 190578828Sobrien return; 190678828Sobrien } 190733965Sjdp s->bsym->flags |= BSF_GLOBAL; 190877298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 190933965Sjdp} 191033965Sjdp 191133965Sjdpvoid 1912130561SobrienS_CLEAR_EXTERNAL (symbolS *s) 191333965Sjdp{ 191460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 191560484Sobrien return; 191633965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 191733965Sjdp { 191833965Sjdp /* Let .weak override. */ 191933965Sjdp return; 192033965Sjdp } 192133965Sjdp s->bsym->flags |= BSF_LOCAL; 192277298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 192333965Sjdp} 192433965Sjdp 192533965Sjdpvoid 1926130561SobrienS_SET_WEAK (symbolS *s) 192733965Sjdp{ 192860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 192960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 193033965Sjdp s->bsym->flags |= BSF_WEAK; 193177298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 193233965Sjdp} 193333965Sjdp 193433965Sjdpvoid 1935130561SobrienS_SET_THREAD_LOCAL (symbolS *s) 193633965Sjdp{ 193760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 1938130561Sobrien s = local_symbol_convert ((struct local_symbol *) s); 1939130561Sobrien if (bfd_is_com_section (s->bsym->section) 1940130561Sobrien && (s->bsym->flags & BSF_THREAD_LOCAL) != 0) 1941130561Sobrien return; 1942130561Sobrien s->bsym->flags |= BSF_THREAD_LOCAL; 1943130561Sobrien if ((s->bsym->flags & BSF_FUNCTION) != 0) 1944130561Sobrien as_bad (_("Accessing function `%s' as thread-local object"), 1945130561Sobrien S_GET_NAME (s)); 1946130561Sobrien else if (! bfd_is_und_section (s->bsym->section) 1947130561Sobrien && (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0) 1948130561Sobrien as_bad (_("Accessing `%s' as thread-local object"), 1949130561Sobrien S_GET_NAME (s)); 1950130561Sobrien} 1951130561Sobrien 1952130561Sobrienvoid 1953130561SobrienS_SET_NAME (symbolS *s, char *name) 1954130561Sobrien{ 1955130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 195660484Sobrien { 195760484Sobrien ((struct local_symbol *) s)->lsy_name = name; 195860484Sobrien return; 195960484Sobrien } 196033965Sjdp s->bsym->name = name; 196133965Sjdp} 196233965Sjdp#endif /* BFD_ASSEMBLER */ 196333965Sjdp 196460484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS 196560484Sobrien 196660484Sobrien/* Return the previous symbol in a chain. */ 196760484Sobrien 196860484SobriensymbolS * 1969130561Sobriensymbol_previous (symbolS *s) 197060484Sobrien{ 197160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197260484Sobrien abort (); 197360484Sobrien return s->sy_previous; 197460484Sobrien} 197560484Sobrien 197660484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */ 197760484Sobrien 197860484Sobrien/* Return the next symbol in a chain. */ 197960484Sobrien 198060484SobriensymbolS * 1981130561Sobriensymbol_next (symbolS *s) 198260484Sobrien{ 198360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 198460484Sobrien abort (); 198560484Sobrien return s->sy_next; 198660484Sobrien} 198760484Sobrien 198860484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 198960484Sobrien 199060484SobrienexpressionS * 1991130561Sobriensymbol_get_value_expression (symbolS *s) 199260484Sobrien{ 199360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 199460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 199560484Sobrien return &s->sy_value; 199660484Sobrien} 199760484Sobrien 199860484Sobrien/* Set the value of a symbol to an expression. */ 199960484Sobrien 200033965Sjdpvoid 2001130561Sobriensymbol_set_value_expression (symbolS *s, const expressionS *exp) 200260484Sobrien{ 200360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 200460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 200560484Sobrien s->sy_value = *exp; 200660484Sobrien} 200760484Sobrien 2008130561Sobrien/* Set the value of SYM to the current position in the current segment. */ 2009130561Sobrien 2010130561Sobrienvoid 2011130561Sobriensymbol_set_value_now (symbolS *sym) 2012130561Sobrien{ 2013130561Sobrien S_SET_SEGMENT (sym, now_seg); 2014130561Sobrien S_SET_VALUE (sym, frag_now_fix ()); 2015130561Sobrien symbol_set_frag (sym, frag_now); 2016130561Sobrien} 2017130561Sobrien 201860484Sobrien/* Set the frag of a symbol. */ 201960484Sobrien 202060484Sobrienvoid 2021130561Sobriensymbol_set_frag (symbolS *s, fragS *f) 202260484Sobrien{ 202360484Sobrien#ifdef BFD_ASSEMBLER 202460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202560484Sobrien { 202660484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 202760484Sobrien return; 202860484Sobrien } 202960484Sobrien#endif 203060484Sobrien s->sy_frag = f; 203160484Sobrien} 203260484Sobrien 203360484Sobrien/* Return the frag of a symbol. */ 203460484Sobrien 203560484SobrienfragS * 2036130561Sobriensymbol_get_frag (symbolS *s) 203760484Sobrien{ 203860484Sobrien#ifdef BFD_ASSEMBLER 203960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 204060484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 204160484Sobrien#endif 204260484Sobrien return s->sy_frag; 204360484Sobrien} 204460484Sobrien 204560484Sobrien/* Mark a symbol as having been used. */ 204660484Sobrien 204760484Sobrienvoid 2048130561Sobriensymbol_mark_used (symbolS *s) 204960484Sobrien{ 205060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 205160484Sobrien return; 205260484Sobrien s->sy_used = 1; 205360484Sobrien} 205460484Sobrien 205560484Sobrien/* Clear the mark of whether a symbol has been used. */ 205660484Sobrien 205760484Sobrienvoid 2058130561Sobriensymbol_clear_used (symbolS *s) 205960484Sobrien{ 206060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 206160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 206260484Sobrien s->sy_used = 0; 206360484Sobrien} 206460484Sobrien 206560484Sobrien/* Return whether a symbol has been used. */ 206660484Sobrien 206760484Sobrienint 2068130561Sobriensymbol_used_p (symbolS *s) 206960484Sobrien{ 207060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207160484Sobrien return 1; 207260484Sobrien return s->sy_used; 207360484Sobrien} 207460484Sobrien 207560484Sobrien/* Mark a symbol as having been used in a reloc. */ 207660484Sobrien 207760484Sobrienvoid 2078130561Sobriensymbol_mark_used_in_reloc (symbolS *s) 207960484Sobrien{ 208060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 208160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 208260484Sobrien s->sy_used_in_reloc = 1; 208360484Sobrien} 208460484Sobrien 208560484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 208660484Sobrien 208760484Sobrienvoid 2088130561Sobriensymbol_clear_used_in_reloc (symbolS *s) 208960484Sobrien{ 209060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 209160484Sobrien return; 209260484Sobrien s->sy_used_in_reloc = 0; 209360484Sobrien} 209460484Sobrien 209560484Sobrien/* Return whether a symbol has been used in a reloc. */ 209660484Sobrien 209760484Sobrienint 2098130561Sobriensymbol_used_in_reloc_p (symbolS *s) 209960484Sobrien{ 210060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 210160484Sobrien return 0; 210260484Sobrien return s->sy_used_in_reloc; 210360484Sobrien} 210460484Sobrien 210560484Sobrien/* Mark a symbol as an MRI common symbol. */ 210660484Sobrien 210760484Sobrienvoid 2108130561Sobriensymbol_mark_mri_common (symbolS *s) 210960484Sobrien{ 211060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 211160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 211260484Sobrien s->sy_mri_common = 1; 211360484Sobrien} 211460484Sobrien 211560484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 211660484Sobrien 211760484Sobrienvoid 2118130561Sobriensymbol_clear_mri_common (symbolS *s) 211960484Sobrien{ 212060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212160484Sobrien return; 212260484Sobrien s->sy_mri_common = 0; 212360484Sobrien} 212460484Sobrien 212560484Sobrien/* Return whether a symbol is an MRI common symbol. */ 212660484Sobrien 212760484Sobrienint 2128130561Sobriensymbol_mri_common_p (symbolS *s) 212960484Sobrien{ 213060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213160484Sobrien return 0; 213260484Sobrien return s->sy_mri_common; 213360484Sobrien} 213460484Sobrien 213560484Sobrien/* Mark a symbol as having been written. */ 213660484Sobrien 213760484Sobrienvoid 2138130561Sobriensymbol_mark_written (symbolS *s) 213960484Sobrien{ 214060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 214160484Sobrien return; 214260484Sobrien s->written = 1; 214360484Sobrien} 214460484Sobrien 214560484Sobrien/* Clear the mark of whether a symbol has been written. */ 214660484Sobrien 214760484Sobrienvoid 2148130561Sobriensymbol_clear_written (symbolS *s) 214960484Sobrien{ 215060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 215160484Sobrien return; 215260484Sobrien s->written = 0; 215360484Sobrien} 215460484Sobrien 215560484Sobrien/* Return whether a symbol has been written. */ 215660484Sobrien 215760484Sobrienint 2158130561Sobriensymbol_written_p (symbolS *s) 215960484Sobrien{ 216060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 216160484Sobrien return 0; 216260484Sobrien return s->written; 216360484Sobrien} 216460484Sobrien 216560484Sobrien/* Mark a symbol has having been resolved. */ 216660484Sobrien 216760484Sobrienvoid 2168130561Sobriensymbol_mark_resolved (symbolS *s) 216960484Sobrien{ 217060484Sobrien#ifdef BFD_ASSEMBLER 217160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217260484Sobrien { 217360484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 217460484Sobrien return; 217560484Sobrien } 217660484Sobrien#endif 217760484Sobrien s->sy_resolved = 1; 217860484Sobrien} 217960484Sobrien 218060484Sobrien/* Return whether a symbol has been resolved. */ 218160484Sobrien 218260484Sobrienint 2183130561Sobriensymbol_resolved_p (symbolS *s) 218460484Sobrien{ 218560484Sobrien#ifdef BFD_ASSEMBLER 218660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 218760484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 218860484Sobrien#endif 218960484Sobrien return s->sy_resolved; 219060484Sobrien} 219160484Sobrien 219260484Sobrien/* Return whether a symbol is a section symbol. */ 219360484Sobrien 219460484Sobrienint 2195130561Sobriensymbol_section_p (symbolS *s ATTRIBUTE_UNUSED) 219660484Sobrien{ 219760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 219860484Sobrien return 0; 219960484Sobrien#ifdef BFD_ASSEMBLER 220060484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 220160484Sobrien#else 220277298Sobrien /* FIXME. */ 220360484Sobrien return 0; 220460484Sobrien#endif 220560484Sobrien} 220660484Sobrien 220760484Sobrien/* Return whether a symbol is equated to another symbol. */ 220860484Sobrien 220960484Sobrienint 2210130561Sobriensymbol_equated_p (symbolS *s) 221160484Sobrien{ 221260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 221360484Sobrien return 0; 221460484Sobrien return s->sy_value.X_op == O_symbol; 221560484Sobrien} 221660484Sobrien 221789857Sobrien/* Return whether a symbol is equated to another symbol, and should be 221889857Sobrien treated specially when writing out relocs. */ 221989857Sobrien 222089857Sobrienint 2221130561Sobriensymbol_equated_reloc_p (symbolS *s) 222289857Sobrien{ 222389857Sobrien if (LOCAL_SYMBOL_CHECK (s)) 222489857Sobrien return 0; 222589857Sobrien /* X_op_symbol, normally not used for O_symbol, is set by 222689857Sobrien resolve_symbol_value to flag expression syms that have been 222789857Sobrien equated. */ 222889857Sobrien return (s->sy_value.X_op == O_symbol 222989857Sobrien && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL) 223089857Sobrien || ! S_IS_DEFINED (s) 223189857Sobrien || S_IS_COMMON (s))); 223289857Sobrien} 223389857Sobrien 223460484Sobrien/* Return whether a symbol has a constant value. */ 223560484Sobrien 223660484Sobrienint 2237130561Sobriensymbol_constant_p (symbolS *s) 223860484Sobrien{ 223960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 224060484Sobrien return 1; 224160484Sobrien return s->sy_value.X_op == O_constant; 224260484Sobrien} 224360484Sobrien 224460484Sobrien#ifdef BFD_ASSEMBLER 224560484Sobrien 224660484Sobrien/* Return the BFD symbol for a symbol. */ 224760484Sobrien 224860484Sobrienasymbol * 2249130561Sobriensymbol_get_bfdsym (symbolS *s) 225060484Sobrien{ 225160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 225260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 225360484Sobrien return s->bsym; 225460484Sobrien} 225560484Sobrien 225660484Sobrien/* Set the BFD symbol for a symbol. */ 225760484Sobrien 225860484Sobrienvoid 2259130561Sobriensymbol_set_bfdsym (symbolS *s, asymbol *bsym) 226060484Sobrien{ 226160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 226260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 226360484Sobrien s->bsym = bsym; 226460484Sobrien} 226560484Sobrien 226660484Sobrien#endif /* BFD_ASSEMBLER */ 226760484Sobrien 226860484Sobrien#ifdef OBJ_SYMFIELD_TYPE 226960484Sobrien 227060484Sobrien/* Get a pointer to the object format information for a symbol. */ 227160484Sobrien 227260484SobrienOBJ_SYMFIELD_TYPE * 2273130561Sobriensymbol_get_obj (symbolS *s) 227460484Sobrien{ 227560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 227660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 227760484Sobrien return &s->sy_obj; 227860484Sobrien} 227960484Sobrien 228060484Sobrien/* Set the object format information for a symbol. */ 228160484Sobrien 228260484Sobrienvoid 2283130561Sobriensymbol_set_obj (symbolS *s, OBJ_SYMFIELD_TYPE *o) 228460484Sobrien{ 228560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 228660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 228760484Sobrien s->sy_obj = *o; 228860484Sobrien} 228960484Sobrien 229060484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 229160484Sobrien 229260484Sobrien#ifdef TC_SYMFIELD_TYPE 229360484Sobrien 229460484Sobrien/* Get a pointer to the processor information for a symbol. */ 229560484Sobrien 229660484SobrienTC_SYMFIELD_TYPE * 2297130561Sobriensymbol_get_tc (symbolS *s) 229860484Sobrien{ 229960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 230060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 230160484Sobrien return &s->sy_tc; 230260484Sobrien} 230360484Sobrien 230460484Sobrien/* Set the processor information for a symbol. */ 230560484Sobrien 230660484Sobrienvoid 2307130561Sobriensymbol_set_tc (symbolS *s, TC_SYMFIELD_TYPE *o) 230860484Sobrien{ 230960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 231060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 231160484Sobrien s->sy_tc = *o; 231260484Sobrien} 231360484Sobrien 231460484Sobrien#endif /* TC_SYMFIELD_TYPE */ 231560484Sobrien 231660484Sobrienvoid 2317130561Sobriensymbol_begin (void) 231833965Sjdp{ 231933965Sjdp symbol_lastP = NULL; 232077298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 232133965Sjdp sy_hash = hash_new (); 232260484Sobrien#ifdef BFD_ASSEMBLER 232360484Sobrien local_hash = hash_new (); 232460484Sobrien#endif 232533965Sjdp 232633965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 232733965Sjdp#ifdef BFD_ASSEMBLER 232833965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 232933965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 233033965Sjdp#endif 233133965Sjdp#else 233277298Sobrien /* Can't initialise a union. Sigh. */ 233333965Sjdp S_SET_SEGMENT (&abs_symbol, absolute_section); 233433965Sjdp#endif 233533965Sjdp abs_symbol.sy_value.X_op = O_constant; 233633965Sjdp abs_symbol.sy_frag = &zero_address_frag; 233733965Sjdp 233833965Sjdp if (LOCAL_LABELS_FB) 233933965Sjdp fb_label_init (); 234033965Sjdp} 234133965Sjdp 234233965Sjdpint indent_level; 234333965Sjdp 234460484Sobrien/* Maximum indent level. 234560484Sobrien Available for modification inside a gdb session. */ 234660484Sobrienint max_indent_level = 8; 234760484Sobrien 234833965Sjdp#if 0 234933965Sjdp 235033965Sjdpstatic void 2351130561Sobrienindent (void) 235233965Sjdp{ 235333965Sjdp printf ("%*s", indent_level * 4, ""); 235433965Sjdp} 235533965Sjdp 235633965Sjdp#endif 235733965Sjdp 235833965Sjdpvoid 2359130561Sobrienprint_symbol_value_1 (FILE *file, symbolS *sym) 236033965Sjdp{ 236133965Sjdp const char *name = S_GET_NAME (sym); 236233965Sjdp if (!name || !name[0]) 236333965Sjdp name = "(unnamed)"; 236433965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 236560484Sobrien 236660484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 236760484Sobrien { 236860484Sobrien#ifdef BFD_ASSEMBLER 236960484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 237060484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 237160484Sobrien && local_symbol_get_frag (locsym) != NULL) 237260484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 237360484Sobrien if (local_symbol_resolved_p (locsym)) 237460484Sobrien fprintf (file, " resolved"); 237560484Sobrien fprintf (file, " local"); 237660484Sobrien#endif 237760484Sobrien } 237860484Sobrien else 237960484Sobrien { 238060484Sobrien if (sym->sy_frag != &zero_address_frag) 238160484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 238260484Sobrien if (sym->written) 238360484Sobrien fprintf (file, " written"); 238460484Sobrien if (sym->sy_resolved) 238560484Sobrien fprintf (file, " resolved"); 238660484Sobrien else if (sym->sy_resolving) 238760484Sobrien fprintf (file, " resolving"); 238860484Sobrien if (sym->sy_used_in_reloc) 238960484Sobrien fprintf (file, " used-in-reloc"); 239060484Sobrien if (sym->sy_used) 239160484Sobrien fprintf (file, " used"); 239260484Sobrien if (S_IS_LOCAL (sym)) 239360484Sobrien fprintf (file, " local"); 239460484Sobrien if (S_IS_EXTERN (sym)) 239560484Sobrien fprintf (file, " extern"); 239660484Sobrien if (S_IS_DEBUG (sym)) 239760484Sobrien fprintf (file, " debug"); 239860484Sobrien if (S_IS_DEFINED (sym)) 239960484Sobrien fprintf (file, " defined"); 240060484Sobrien } 240133965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 240260484Sobrien if (symbol_resolved_p (sym)) 240333965Sjdp { 240433965Sjdp segT s = S_GET_SEGMENT (sym); 240533965Sjdp 240633965Sjdp if (s != undefined_section 2407104834Sobrien && s != expr_section) 240833965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 240933965Sjdp } 241060484Sobrien else if (indent_level < max_indent_level 241160484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 241233965Sjdp { 241333965Sjdp indent_level++; 241433965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 241560484Sobrien#ifdef BFD_ASSEMBLER 241660484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 241760484Sobrien fprintf (file, "constant %lx", 241889857Sobrien (long) ((struct local_symbol *) sym)->lsy_value); 241960484Sobrien else 242060484Sobrien#endif 242160484Sobrien print_expr_1 (file, &sym->sy_value); 242233965Sjdp fprintf (file, ">"); 242333965Sjdp indent_level--; 242433965Sjdp } 242533965Sjdp fflush (file); 242633965Sjdp} 242733965Sjdp 242833965Sjdpvoid 2429130561Sobrienprint_symbol_value (symbolS *sym) 243033965Sjdp{ 243133965Sjdp indent_level = 0; 243233965Sjdp print_symbol_value_1 (stderr, sym); 243333965Sjdp fprintf (stderr, "\n"); 243433965Sjdp} 243533965Sjdp 243660484Sobrienstatic void 2437130561Sobrienprint_binary (FILE *file, const char *name, expressionS *exp) 243860484Sobrien{ 243960484Sobrien indent_level++; 244060484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 244160484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 244260484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 244360484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 244460484Sobrien fprintf (file, ">"); 244560484Sobrien indent_level--; 244660484Sobrien} 244760484Sobrien 244833965Sjdpvoid 2449130561Sobrienprint_expr_1 (FILE *file, expressionS *exp) 245033965Sjdp{ 245133965Sjdp fprintf (file, "expr %lx ", (long) exp); 245233965Sjdp switch (exp->X_op) 245333965Sjdp { 245433965Sjdp case O_illegal: 245533965Sjdp fprintf (file, "illegal"); 245633965Sjdp break; 245733965Sjdp case O_absent: 245833965Sjdp fprintf (file, "absent"); 245933965Sjdp break; 246033965Sjdp case O_constant: 246133965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 246233965Sjdp break; 246333965Sjdp case O_symbol: 246433965Sjdp indent_level++; 246533965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 246633965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 246733965Sjdp fprintf (file, ">"); 246833965Sjdp maybe_print_addnum: 246933965Sjdp if (exp->X_add_number) 247033965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 247133965Sjdp (long) exp->X_add_number); 247233965Sjdp indent_level--; 247333965Sjdp break; 247433965Sjdp case O_register: 247533965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 247633965Sjdp break; 247733965Sjdp case O_big: 247833965Sjdp fprintf (file, "big"); 247933965Sjdp break; 248033965Sjdp case O_uminus: 248133965Sjdp fprintf (file, "uminus -<"); 248233965Sjdp indent_level++; 248333965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 248433965Sjdp fprintf (file, ">"); 248533965Sjdp goto maybe_print_addnum; 248633965Sjdp case O_bit_not: 248733965Sjdp fprintf (file, "bit_not"); 248833965Sjdp break; 248933965Sjdp case O_multiply: 249060484Sobrien print_binary (file, "multiply", exp); 249133965Sjdp break; 249233965Sjdp case O_divide: 249360484Sobrien print_binary (file, "divide", exp); 249433965Sjdp break; 249533965Sjdp case O_modulus: 249660484Sobrien print_binary (file, "modulus", exp); 249733965Sjdp break; 249833965Sjdp case O_left_shift: 249960484Sobrien print_binary (file, "lshift", exp); 250033965Sjdp break; 250133965Sjdp case O_right_shift: 250260484Sobrien print_binary (file, "rshift", exp); 250333965Sjdp break; 250433965Sjdp case O_bit_inclusive_or: 250560484Sobrien print_binary (file, "bit_ior", exp); 250633965Sjdp break; 250733965Sjdp case O_bit_exclusive_or: 250860484Sobrien print_binary (file, "bit_xor", exp); 250933965Sjdp break; 251033965Sjdp case O_bit_and: 251160484Sobrien print_binary (file, "bit_and", exp); 251233965Sjdp break; 251333965Sjdp case O_eq: 251460484Sobrien print_binary (file, "eq", exp); 251533965Sjdp break; 251633965Sjdp case O_ne: 251760484Sobrien print_binary (file, "ne", exp); 251833965Sjdp break; 251933965Sjdp case O_lt: 252060484Sobrien print_binary (file, "lt", exp); 252133965Sjdp break; 252233965Sjdp case O_le: 252360484Sobrien print_binary (file, "le", exp); 252433965Sjdp break; 252533965Sjdp case O_ge: 252660484Sobrien print_binary (file, "ge", exp); 252733965Sjdp break; 252833965Sjdp case O_gt: 252960484Sobrien print_binary (file, "gt", exp); 253033965Sjdp break; 253133965Sjdp case O_logical_and: 253260484Sobrien print_binary (file, "logical_and", exp); 253333965Sjdp break; 253433965Sjdp case O_logical_or: 253560484Sobrien print_binary (file, "logical_or", exp); 253633965Sjdp break; 253733965Sjdp case O_add: 253833965Sjdp indent_level++; 253933965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 254033965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 254133965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 254233965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 254333965Sjdp fprintf (file, ">"); 254433965Sjdp goto maybe_print_addnum; 254533965Sjdp case O_subtract: 254633965Sjdp indent_level++; 254733965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 254833965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 254933965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 255033965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 255133965Sjdp fprintf (file, ">"); 255233965Sjdp goto maybe_print_addnum; 255333965Sjdp default: 255433965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 255533965Sjdp break; 255633965Sjdp } 255733965Sjdp fflush (stdout); 255833965Sjdp} 255933965Sjdp 256033965Sjdpvoid 2561130561Sobrienprint_expr (expressionS *exp) 256233965Sjdp{ 256333965Sjdp print_expr_1 (stderr, exp); 256433965Sjdp fprintf (stderr, "\n"); 256533965Sjdp} 256633965Sjdp 256733965Sjdpvoid 2568130561Sobriensymbol_print_statistics (FILE *file) 256933965Sjdp{ 257033965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 257160484Sobrien#ifdef BFD_ASSEMBLER 257260484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 257360484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 257460484Sobrien local_symbol_count, local_symbol_conversion_count); 257560484Sobrien#endif 257633965Sjdp} 2577