symbols.c revision 89857
133965Sjdp/* symbols.c -symbol table- 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 378828Sobrien 1999, 2000, 2001 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 6389857Sobrienstatic char *save_symbol_name PARAMS ((const char *)); 6433965Sjdpstatic void fb_label_init PARAMS ((void)); 6533965Sjdpstatic long dollar_label_instance PARAMS ((long)); 6633965Sjdpstatic long fb_label_instance PARAMS ((long)); 6733965Sjdp 6860484Sobrienstatic void print_binary PARAMS ((FILE *, const char *, expressionS *)); 6960484Sobrien 7077298Sobrien/* Return a pointer to a new symbol. Die if we can't make a new 7133965Sjdp symbol. Fill in the symbol's values. Add symbol to end of symbol 7233965Sjdp chain. 7377298Sobrien 7433965Sjdp This function should be called in the general case of creating a 7533965Sjdp symbol. However, if the output file symbol table has already been 7633965Sjdp set, and you are certain that this symbol won't be wanted in the 7733965Sjdp output file, you can call symbol_create. */ 7833965Sjdp 7933965SjdpsymbolS * 8033965Sjdpsymbol_new (name, segment, valu, frag) 8133965Sjdp const char *name; 8233965Sjdp segT segment; 8333965Sjdp valueT valu; 8433965Sjdp fragS *frag; 8533965Sjdp{ 8633965Sjdp symbolS *symbolP = symbol_create (name, segment, valu, frag); 8733965Sjdp 8877298Sobrien /* Link to end of symbol chain. */ 8933965Sjdp#ifdef BFD_ASSEMBLER 9033965Sjdp { 9133965Sjdp extern int symbol_table_frozen; 9233965Sjdp if (symbol_table_frozen) 9333965Sjdp abort (); 9433965Sjdp } 9533965Sjdp#endif 9633965Sjdp symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP); 9733965Sjdp 9833965Sjdp return symbolP; 9933965Sjdp} 10033965Sjdp 10160484Sobrien/* Save a symbol name on a permanent obstack, and convert it according 10260484Sobrien to the object file format. */ 10360484Sobrien 10460484Sobrienstatic char * 10560484Sobriensave_symbol_name (name) 10660484Sobrien const char *name; 10733965Sjdp{ 10833965Sjdp unsigned int name_length; 10960484Sobrien char *ret; 11033965Sjdp 11177298Sobrien name_length = strlen (name) + 1; /* +1 for \0. */ 11233965Sjdp obstack_grow (¬es, name, name_length); 11360484Sobrien ret = obstack_finish (¬es); 11460484Sobrien 11533965Sjdp#ifdef STRIP_UNDERSCORE 11660484Sobrien if (ret[0] == '_') 11760484Sobrien ++ret; 11833965Sjdp#endif 11933965Sjdp 12033965Sjdp#ifdef tc_canonicalize_symbol_name 12160484Sobrien ret = tc_canonicalize_symbol_name (ret); 12233965Sjdp#endif 12333965Sjdp 12433965Sjdp if (! symbols_case_sensitive) 12533965Sjdp { 12689857Sobrien char *s; 12733965Sjdp 12889857Sobrien for (s = ret; *s != '\0'; s++) 12989857Sobrien *s = TOUPPER (*s); 13033965Sjdp } 13133965Sjdp 13260484Sobrien return ret; 13360484Sobrien} 13460484Sobrien 13560484SobriensymbolS * 13660484Sobriensymbol_create (name, segment, valu, frag) 13777298Sobrien const char *name; /* It is copied, the caller can destroy/modify. */ 13877298Sobrien segT segment; /* Segment identifier (SEG_<something>). */ 13977298Sobrien valueT valu; /* Symbol value. */ 14077298Sobrien fragS *frag; /* Associated fragment. */ 14160484Sobrien{ 14260484Sobrien char *preserved_copy_of_name; 14360484Sobrien symbolS *symbolP; 14460484Sobrien 14560484Sobrien preserved_copy_of_name = save_symbol_name (name); 14660484Sobrien 14733965Sjdp symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS)); 14833965Sjdp 14977298Sobrien /* symbol must be born in some fixed state. This seems as good as any. */ 15033965Sjdp memset (symbolP, 0, sizeof (symbolS)); 15133965Sjdp 15233965Sjdp#ifdef BFD_ASSEMBLER 15333965Sjdp symbolP->bsym = bfd_make_empty_symbol (stdoutput); 15433965Sjdp if (symbolP->bsym == NULL) 15533965Sjdp as_perror ("%s", "bfd_make_empty_symbol"); 15633965Sjdp symbolP->bsym->udata.p = (PTR) symbolP; 15733965Sjdp#endif 15833965Sjdp S_SET_NAME (symbolP, preserved_copy_of_name); 15933965Sjdp 16033965Sjdp S_SET_SEGMENT (symbolP, segment); 16133965Sjdp S_SET_VALUE (symbolP, valu); 16233965Sjdp symbol_clear_list_pointers (symbolP); 16333965Sjdp 16433965Sjdp symbolP->sy_frag = frag; 16533965Sjdp#ifndef BFD_ASSEMBLER 16633965Sjdp symbolP->sy_number = ~0; 16733965Sjdp symbolP->sy_name_offset = (unsigned int) ~0; 16833965Sjdp#endif 16933965Sjdp 17033965Sjdp obj_symbol_new_hook (symbolP); 17133965Sjdp 17233965Sjdp#ifdef tc_symbol_new_hook 17333965Sjdp tc_symbol_new_hook (symbolP); 17433965Sjdp#endif 17533965Sjdp 17633965Sjdp return symbolP; 17733965Sjdp} 17833965Sjdp 17960484Sobrien#ifdef BFD_ASSEMBLER 18033965Sjdp 18160484Sobrien/* Local symbol support. If we can get away with it, we keep only a 18260484Sobrien small amount of information for local symbols. */ 18360484Sobrien 18460484Sobrienstatic struct local_symbol *local_symbol_make PARAMS ((const char *, segT, 18560484Sobrien valueT, fragS *)); 18660484Sobrienstatic symbolS *local_symbol_convert PARAMS ((struct local_symbol *)); 18760484Sobrien 18860484Sobrien/* Used for statistics. */ 18960484Sobrien 19060484Sobrienstatic unsigned long local_symbol_count; 19160484Sobrienstatic unsigned long local_symbol_conversion_count; 19260484Sobrien 19360484Sobrien/* This macro is called with a symbol argument passed by reference. 19460484Sobrien It returns whether this is a local symbol. If necessary, it 19560484Sobrien changes its argument to the real symbol. */ 19660484Sobrien 19760484Sobrien#define LOCAL_SYMBOL_CHECK(s) \ 19860484Sobrien (s->bsym == NULL \ 19960484Sobrien ? (local_symbol_converted_p ((struct local_symbol *) s) \ 20060484Sobrien ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s), \ 20160484Sobrien 0) \ 20260484Sobrien : 1) \ 20360484Sobrien : 0) 20460484Sobrien 20560484Sobrien/* Create a local symbol and insert it into the local hash table. */ 20660484Sobrien 20760484Sobrienstatic struct local_symbol * 20889857Sobrienlocal_symbol_make (name, section, value, frag) 20960484Sobrien const char *name; 21060484Sobrien segT section; 21189857Sobrien valueT value; 21260484Sobrien fragS *frag; 21360484Sobrien{ 21460484Sobrien char *name_copy; 21560484Sobrien struct local_symbol *ret; 21660484Sobrien 21760484Sobrien ++local_symbol_count; 21860484Sobrien 21960484Sobrien name_copy = save_symbol_name (name); 22060484Sobrien 22160484Sobrien ret = (struct local_symbol *) obstack_alloc (¬es, sizeof *ret); 22260484Sobrien ret->lsy_marker = NULL; 22360484Sobrien ret->lsy_name = name_copy; 22460484Sobrien ret->lsy_section = section; 22560484Sobrien local_symbol_set_frag (ret, frag); 22689857Sobrien ret->lsy_value = value; 22760484Sobrien 22860484Sobrien hash_jam (local_hash, name_copy, (PTR) ret); 22960484Sobrien 23060484Sobrien return ret; 23160484Sobrien} 23260484Sobrien 23360484Sobrien/* Convert a local symbol into a real symbol. Note that we do not 23460484Sobrien reclaim the space used by the local symbol. */ 23560484Sobrien 23660484Sobrienstatic symbolS * 23760484Sobrienlocal_symbol_convert (locsym) 23860484Sobrien struct local_symbol *locsym; 23960484Sobrien{ 24060484Sobrien symbolS *ret; 24160484Sobrien 24260484Sobrien assert (locsym->lsy_marker == NULL); 24360484Sobrien if (local_symbol_converted_p (locsym)) 24460484Sobrien return local_symbol_get_real_symbol (locsym); 24560484Sobrien 24660484Sobrien ++local_symbol_conversion_count; 24760484Sobrien 24889857Sobrien ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value, 24960484Sobrien local_symbol_get_frag (locsym)); 25060484Sobrien 25160484Sobrien if (local_symbol_resolved_p (locsym)) 25260484Sobrien ret->sy_resolved = 1; 25360484Sobrien 25460484Sobrien /* Local symbols are always either defined or used. */ 25560484Sobrien ret->sy_used = 1; 25660484Sobrien 25789857Sobrien#ifdef TC_LOCAL_SYMFIELD_CONVERT 25889857Sobrien TC_LOCAL_SYMFIELD_CONVERT (locsym, ret); 25989857Sobrien#endif 26089857Sobrien 26160484Sobrien symbol_table_insert (ret); 26260484Sobrien 26360484Sobrien local_symbol_mark_converted (locsym); 26460484Sobrien local_symbol_set_real_symbol (locsym, ret); 26560484Sobrien 26660484Sobrien hash_jam (local_hash, locsym->lsy_name, NULL); 26760484Sobrien 26860484Sobrien return ret; 26960484Sobrien} 27060484Sobrien 27160484Sobrien#else /* ! BFD_ASSEMBLER */ 27260484Sobrien 27360484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0 27460484Sobrien#define local_symbol_convert(s) ((symbolS *) s) 27560484Sobrien 27660484Sobrien#endif /* ! BFD_ASSEMBLER */ 27760484Sobrien 27877298Sobrien/* We have just seen "<name>:". 27977298Sobrien Creates a struct symbol unless it already exists. 28060484Sobrien 28177298Sobrien Gripes if we are redefining a symbol incompatibly (and ignores it). */ 28277298Sobrien 28333965SjdpsymbolS * 28477298Sobriencolon (sym_name) /* Just seen "x:" - rattle symbols & frags. */ 28577298Sobrien const char *sym_name; /* Symbol name, as a cannonical string. */ 28677298Sobrien /* We copy this string: OK to alter later. */ 28733965Sjdp{ 28877298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 28933965Sjdp 29033965Sjdp /* Sun local labels go out of scope whenever a non-local symbol is 29133965Sjdp defined. */ 29233965Sjdp if (LOCAL_LABELS_DOLLAR) 29333965Sjdp { 29433965Sjdp int local; 29533965Sjdp 29633965Sjdp#ifdef BFD_ASSEMBLER 29733965Sjdp local = bfd_is_local_label_name (stdoutput, sym_name); 29833965Sjdp#else 29933965Sjdp local = LOCAL_LABEL (sym_name); 30033965Sjdp#endif 30133965Sjdp 30233965Sjdp if (! local) 30333965Sjdp dollar_label_clear (); 30433965Sjdp } 30533965Sjdp 30633965Sjdp#ifndef WORKING_DOT_WORD 30733965Sjdp if (new_broken_words) 30833965Sjdp { 30933965Sjdp struct broken_word *a; 31033965Sjdp int possible_bytes; 31133965Sjdp fragS *frag_tmp; 31233965Sjdp char *frag_opcode; 31333965Sjdp 31433965Sjdp extern const int md_short_jump_size; 31533965Sjdp extern const int md_long_jump_size; 31633965Sjdp possible_bytes = (md_short_jump_size 31733965Sjdp + new_broken_words * md_long_jump_size); 31833965Sjdp 31933965Sjdp frag_tmp = frag_now; 32033965Sjdp frag_opcode = frag_var (rs_broken_word, 32133965Sjdp possible_bytes, 32233965Sjdp possible_bytes, 32333965Sjdp (relax_substateT) 0, 32433965Sjdp (symbolS *) broken_words, 32533965Sjdp (offsetT) 0, 32633965Sjdp NULL); 32733965Sjdp 32877298Sobrien /* We want to store the pointer to where to insert the jump 32977298Sobrien table in the fr_opcode of the rs_broken_word frag. This 33077298Sobrien requires a little hackery. */ 33133965Sjdp while (frag_tmp 33233965Sjdp && (frag_tmp->fr_type != rs_broken_word 33333965Sjdp || frag_tmp->fr_opcode)) 33433965Sjdp frag_tmp = frag_tmp->fr_next; 33533965Sjdp know (frag_tmp); 33633965Sjdp frag_tmp->fr_opcode = frag_opcode; 33733965Sjdp new_broken_words = 0; 33833965Sjdp 33933965Sjdp for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word) 34033965Sjdp a->dispfrag = frag_tmp; 34133965Sjdp } 34233965Sjdp#endif /* WORKING_DOT_WORD */ 34333965Sjdp 34433965Sjdp if ((symbolP = symbol_find (sym_name)) != 0) 34533965Sjdp { 34633965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION 34733965Sjdp if (RESOLVE_SYMBOL_REDEFINITION (symbolP)) 34833965Sjdp return symbolP; 34933965Sjdp#endif 35077298Sobrien /* Now check for undefined symbols. */ 35160484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 35233965Sjdp { 35360484Sobrien#ifdef BFD_ASSEMBLER 35460484Sobrien struct local_symbol *locsym = (struct local_symbol *) symbolP; 35560484Sobrien 35660484Sobrien if (locsym->lsy_section != undefined_section 35760484Sobrien && (local_symbol_get_frag (locsym) != frag_now 35860484Sobrien || locsym->lsy_section != now_seg 35989857Sobrien || locsym->lsy_value != frag_now_fix ())) 36060484Sobrien { 36189857Sobrien as_bad (_("symbol `%s' is already defined"), sym_name); 36260484Sobrien return symbolP; 36360484Sobrien } 36460484Sobrien 36560484Sobrien locsym->lsy_section = now_seg; 36660484Sobrien local_symbol_set_frag (locsym, frag_now); 36789857Sobrien locsym->lsy_value = frag_now_fix (); 36860484Sobrien#endif 36960484Sobrien } 37060484Sobrien else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 37160484Sobrien { 37233965Sjdp if (S_GET_VALUE (symbolP) == 0) 37333965Sjdp { 37433965Sjdp symbolP->sy_frag = frag_now; 37533965Sjdp#ifdef OBJ_VMS 37677298Sobrien S_SET_OTHER (symbolP, const_flag); 37733965Sjdp#endif 37833965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 37933965Sjdp S_SET_SEGMENT (symbolP, now_seg); 38033965Sjdp#ifdef N_UNDF 38133965Sjdp know (N_UNDF == 0); 38277298Sobrien#endif /* if we have one, it better be zero. */ 38333965Sjdp 38433965Sjdp } 38533965Sjdp else 38633965Sjdp { 38777298Sobrien /* There are still several cases to check: 38833965Sjdp 38977298Sobrien A .comm/.lcomm symbol being redefined as initialized 39077298Sobrien data is OK 39177298Sobrien 39277298Sobrien A .comm/.lcomm symbol being redefined with a larger 39377298Sobrien size is also OK 39477298Sobrien 39577298Sobrien This only used to be allowed on VMS gas, but Sun cc 39677298Sobrien on the sparc also depends on it. */ 39777298Sobrien 39833965Sjdp if (((!S_IS_DEBUG (symbolP) 39933965Sjdp && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 40033965Sjdp && S_IS_EXTERNAL (symbolP)) 40133965Sjdp || S_GET_SEGMENT (symbolP) == bss_section) 40233965Sjdp && (now_seg == data_section 40333965Sjdp || now_seg == S_GET_SEGMENT (symbolP))) 40433965Sjdp { 40577298Sobrien /* Select which of the 2 cases this is. */ 40633965Sjdp if (now_seg != data_section) 40733965Sjdp { 40877298Sobrien /* New .comm for prev .comm symbol. 40977298Sobrien 41077298Sobrien If the new size is larger we just change its 41177298Sobrien value. If the new size is smaller, we ignore 41277298Sobrien this symbol. */ 41333965Sjdp if (S_GET_VALUE (symbolP) 41433965Sjdp < ((unsigned) frag_now_fix ())) 41533965Sjdp { 41633965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 41733965Sjdp } 41833965Sjdp } 41933965Sjdp else 42033965Sjdp { 42133965Sjdp /* It is a .comm/.lcomm being converted to initialized 42233965Sjdp data. */ 42333965Sjdp symbolP->sy_frag = frag_now; 42433965Sjdp#ifdef OBJ_VMS 42577298Sobrien S_SET_OTHER (symbolP, const_flag); 42633965Sjdp#endif 42733965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 42877298Sobrien S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit. */ 42933965Sjdp } 43033965Sjdp } 43133965Sjdp else 43233965Sjdp { 43360484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \ 43460484Sobrien && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT)) 43560484Sobrien static const char *od_buf = ""; 43633965Sjdp#else 43760484Sobrien char od_buf[100]; 43860484Sobrien od_buf[0] = '\0'; 43960484Sobrien#ifdef BFD_ASSEMBLER 44060484Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 44160484Sobrien#endif 44260484Sobrien sprintf(od_buf, "%d.%d.", 44360484Sobrien S_GET_OTHER (symbolP), 44460484Sobrien S_GET_DESC (symbolP)); 44560484Sobrien#endif 44689857Sobrien as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"), 44733965Sjdp sym_name, 44833965Sjdp segment_name (S_GET_SEGMENT (symbolP)), 44960484Sobrien od_buf, 45033965Sjdp (long) S_GET_VALUE (symbolP)); 45133965Sjdp } 45277298Sobrien } /* if the undefined symbol has no value */ 45333965Sjdp } 45433965Sjdp else 45533965Sjdp { 45677298Sobrien /* Don't blow up if the definition is the same. */ 45733965Sjdp if (!(frag_now == symbolP->sy_frag 45833965Sjdp && S_GET_VALUE (symbolP) == frag_now_fix () 45933965Sjdp && S_GET_SEGMENT (symbolP) == now_seg)) 46089857Sobrien as_bad (_("symbol `%s' is already defined"), sym_name); 46177298Sobrien } 46233965Sjdp 46333965Sjdp } 46460484Sobrien#ifdef BFD_ASSEMBLER 46560484Sobrien else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name)) 46660484Sobrien { 46760484Sobrien symbolP = (symbolS *) local_symbol_make (sym_name, now_seg, 46860484Sobrien (valueT) frag_now_fix (), 46960484Sobrien frag_now); 47060484Sobrien } 47160484Sobrien#endif /* BFD_ASSEMBLER */ 47233965Sjdp else 47333965Sjdp { 47433965Sjdp symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (), 47533965Sjdp frag_now); 47633965Sjdp#ifdef OBJ_VMS 47733965Sjdp S_SET_OTHER (symbolP, const_flag); 47833965Sjdp#endif /* OBJ_VMS */ 47933965Sjdp 48033965Sjdp symbol_table_insert (symbolP); 48177298Sobrien } 48233965Sjdp 48333965Sjdp if (mri_common_symbol != NULL) 48433965Sjdp { 48533965Sjdp /* This symbol is actually being defined within an MRI common 48633965Sjdp section. This requires special handling. */ 48760484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 48860484Sobrien symbolP = local_symbol_convert ((struct local_symbol *) symbolP); 48933965Sjdp symbolP->sy_value.X_op = O_symbol; 49033965Sjdp symbolP->sy_value.X_add_symbol = mri_common_symbol; 49133965Sjdp symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol); 49233965Sjdp symbolP->sy_frag = &zero_address_frag; 49333965Sjdp S_SET_SEGMENT (symbolP, expr_section); 49433965Sjdp symbolP->sy_mri_common = 1; 49533965Sjdp } 49633965Sjdp 49733965Sjdp#ifdef tc_frob_label 49833965Sjdp tc_frob_label (symbolP); 49933965Sjdp#endif 50033965Sjdp#ifdef obj_frob_label 50133965Sjdp obj_frob_label (symbolP); 50233965Sjdp#endif 50333965Sjdp 50433965Sjdp return symbolP; 50533965Sjdp} 50633965Sjdp 50777298Sobrien/* Die if we can't insert the symbol. */ 50833965Sjdp 50977298Sobrienvoid 51033965Sjdpsymbol_table_insert (symbolP) 51133965Sjdp symbolS *symbolP; 51233965Sjdp{ 51333965Sjdp register const char *error_string; 51433965Sjdp 51533965Sjdp know (symbolP); 51633965Sjdp know (S_GET_NAME (symbolP)); 51733965Sjdp 51860484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 51960484Sobrien { 52060484Sobrien error_string = hash_jam (local_hash, S_GET_NAME (symbolP), 52160484Sobrien (PTR) symbolP); 52260484Sobrien if (error_string != NULL) 52389857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 52460484Sobrien S_GET_NAME (symbolP), error_string); 52560484Sobrien return; 52660484Sobrien } 52760484Sobrien 52833965Sjdp if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP))) 52933965Sjdp { 53089857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 53133965Sjdp S_GET_NAME (symbolP), error_string); 53277298Sobrien } /* on error */ 53377298Sobrien} 53433965Sjdp 53577298Sobrien/* If a symbol name does not exist, create it as undefined, and insert 53677298Sobrien it into the symbol table. Return a pointer to it. */ 53777298Sobrien 53833965SjdpsymbolS * 53933965Sjdpsymbol_find_or_make (name) 54033965Sjdp const char *name; 54133965Sjdp{ 54233965Sjdp register symbolS *symbolP; 54333965Sjdp 54433965Sjdp symbolP = symbol_find (name); 54533965Sjdp 54633965Sjdp if (symbolP == NULL) 54733965Sjdp { 54860484Sobrien#ifdef BFD_ASSEMBLER 54960484Sobrien if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name)) 55060484Sobrien { 55160484Sobrien symbolP = md_undefined_symbol ((char *) name); 55260484Sobrien if (symbolP != NULL) 55360484Sobrien return symbolP; 55460484Sobrien 55560484Sobrien symbolP = (symbolS *) local_symbol_make (name, undefined_section, 55660484Sobrien (valueT) 0, 55760484Sobrien &zero_address_frag); 55860484Sobrien return symbolP; 55960484Sobrien } 56060484Sobrien#endif 56160484Sobrien 56233965Sjdp symbolP = symbol_make (name); 56333965Sjdp 56433965Sjdp symbol_table_insert (symbolP); 56533965Sjdp } /* if symbol wasn't found */ 56633965Sjdp 56733965Sjdp return (symbolP); 56877298Sobrien} 56933965Sjdp 57033965SjdpsymbolS * 57133965Sjdpsymbol_make (name) 57233965Sjdp CONST char *name; 57333965Sjdp{ 57433965Sjdp symbolS *symbolP; 57533965Sjdp 57677298Sobrien /* Let the machine description default it, e.g. for register names. */ 57733965Sjdp symbolP = md_undefined_symbol ((char *) name); 57833965Sjdp 57933965Sjdp if (!symbolP) 58033965Sjdp symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag); 58133965Sjdp 58233965Sjdp return (symbolP); 58377298Sobrien} 58433965Sjdp 58577298Sobrien/* Implement symbol table lookup. 58677298Sobrien In: A symbol's name as a string: '\0' can't be part of a symbol name. 58777298Sobrien Out: NULL if the name was not in the symbol table, else the address 58877298Sobrien of a struct symbol associated with that name. */ 58933965Sjdp 59033965SjdpsymbolS * 59133965Sjdpsymbol_find (name) 59233965Sjdp CONST char *name; 59333965Sjdp{ 59433965Sjdp#ifdef STRIP_UNDERSCORE 59533965Sjdp return (symbol_find_base (name, 1)); 59633965Sjdp#else /* STRIP_UNDERSCORE */ 59733965Sjdp return (symbol_find_base (name, 0)); 59833965Sjdp#endif /* STRIP_UNDERSCORE */ 59977298Sobrien} 60033965Sjdp 60133965SjdpsymbolS * 60233965Sjdpsymbol_find_base (name, strip_underscore) 60333965Sjdp CONST char *name; 60433965Sjdp int strip_underscore; 60533965Sjdp{ 60633965Sjdp if (strip_underscore && *name == '_') 60733965Sjdp name++; 60833965Sjdp 60933965Sjdp#ifdef tc_canonicalize_symbol_name 61033965Sjdp { 61133965Sjdp char *copy; 61260484Sobrien size_t len = strlen (name) + 1; 61333965Sjdp 61460484Sobrien copy = (char *) alloca (len); 61560484Sobrien memcpy (copy, name, len); 61633965Sjdp name = tc_canonicalize_symbol_name (copy); 61733965Sjdp } 61833965Sjdp#endif 61933965Sjdp 62033965Sjdp if (! symbols_case_sensitive) 62133965Sjdp { 62260484Sobrien char *copy; 62360484Sobrien const char *orig; 62460484Sobrien unsigned char c; 62533965Sjdp 62660484Sobrien orig = name; 62760484Sobrien name = copy = (char *) alloca (strlen (name) + 1); 62860484Sobrien 62960484Sobrien while ((c = *orig++) != '\0') 63060484Sobrien { 63189857Sobrien *copy++ = TOUPPER (c); 63260484Sobrien } 63360484Sobrien *copy = '\0'; 63433965Sjdp } 63533965Sjdp 63660484Sobrien#ifdef BFD_ASSEMBLER 63760484Sobrien { 63860484Sobrien struct local_symbol *locsym; 63960484Sobrien 64060484Sobrien locsym = (struct local_symbol *) hash_find (local_hash, name); 64160484Sobrien if (locsym != NULL) 64260484Sobrien return (symbolS *) locsym; 64360484Sobrien } 64460484Sobrien#endif 64560484Sobrien 64633965Sjdp return ((symbolS *) hash_find (sy_hash, name)); 64733965Sjdp} 64833965Sjdp 64977298Sobrien/* Once upon a time, symbols were kept in a singly linked list. At 65077298Sobrien least coff needs to be able to rearrange them from time to time, for 65177298Sobrien which a doubly linked list is much more convenient. Loic did these 65277298Sobrien as macros which seemed dangerous to me so they're now functions. 65377298Sobrien xoxorich. */ 65433965Sjdp 65577298Sobrien/* Link symbol ADDME after symbol TARGET in the chain. */ 65677298Sobrien 65777298Sobrienvoid 65833965Sjdpsymbol_append (addme, target, rootPP, lastPP) 65933965Sjdp symbolS *addme; 66033965Sjdp symbolS *target; 66133965Sjdp symbolS **rootPP; 66233965Sjdp symbolS **lastPP; 66333965Sjdp{ 66460484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 66560484Sobrien abort (); 66660484Sobrien if (target != NULL && LOCAL_SYMBOL_CHECK (target)) 66760484Sobrien abort (); 66860484Sobrien 66933965Sjdp if (target == NULL) 67033965Sjdp { 67133965Sjdp know (*rootPP == NULL); 67233965Sjdp know (*lastPP == NULL); 67333965Sjdp addme->sy_next = NULL; 67433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 67533965Sjdp addme->sy_previous = NULL; 67633965Sjdp#endif 67733965Sjdp *rootPP = addme; 67833965Sjdp *lastPP = addme; 67933965Sjdp return; 68077298Sobrien } /* if the list is empty */ 68133965Sjdp 68233965Sjdp if (target->sy_next != NULL) 68333965Sjdp { 68433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 68533965Sjdp target->sy_next->sy_previous = addme; 68633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 68733965Sjdp } 68833965Sjdp else 68933965Sjdp { 69033965Sjdp know (*lastPP == target); 69133965Sjdp *lastPP = addme; 69277298Sobrien } /* if we have a next */ 69333965Sjdp 69433965Sjdp addme->sy_next = target->sy_next; 69533965Sjdp target->sy_next = addme; 69633965Sjdp 69733965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 69833965Sjdp addme->sy_previous = target; 69933965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 70033965Sjdp 70133965Sjdp debug_verify_symchain (symbol_rootP, symbol_lastP); 70233965Sjdp} 70333965Sjdp 70477298Sobrien/* Set the chain pointers of SYMBOL to null. */ 70577298Sobrien 70677298Sobrienvoid 70733965Sjdpsymbol_clear_list_pointers (symbolP) 70833965Sjdp symbolS *symbolP; 70933965Sjdp{ 71060484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 71160484Sobrien abort (); 71233965Sjdp symbolP->sy_next = NULL; 71333965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 71433965Sjdp symbolP->sy_previous = NULL; 71533965Sjdp#endif 71633965Sjdp} 71733965Sjdp 71833965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 71977298Sobrien/* Remove SYMBOLP from the list. */ 72077298Sobrien 72177298Sobrienvoid 72233965Sjdpsymbol_remove (symbolP, rootPP, lastPP) 72333965Sjdp symbolS *symbolP; 72433965Sjdp symbolS **rootPP; 72533965Sjdp symbolS **lastPP; 72633965Sjdp{ 72760484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 72860484Sobrien abort (); 72960484Sobrien 73033965Sjdp if (symbolP == *rootPP) 73133965Sjdp { 73233965Sjdp *rootPP = symbolP->sy_next; 73377298Sobrien } /* if it was the root */ 73433965Sjdp 73533965Sjdp if (symbolP == *lastPP) 73633965Sjdp { 73733965Sjdp *lastPP = symbolP->sy_previous; 73877298Sobrien } /* if it was the tail */ 73933965Sjdp 74033965Sjdp if (symbolP->sy_next != NULL) 74133965Sjdp { 74233965Sjdp symbolP->sy_next->sy_previous = symbolP->sy_previous; 74377298Sobrien } /* if not last */ 74433965Sjdp 74533965Sjdp if (symbolP->sy_previous != NULL) 74633965Sjdp { 74733965Sjdp symbolP->sy_previous->sy_next = symbolP->sy_next; 74877298Sobrien } /* if not first */ 74933965Sjdp 75033965Sjdp debug_verify_symchain (*rootPP, *lastPP); 75133965Sjdp} 75233965Sjdp 75377298Sobrien/* Link symbol ADDME before symbol TARGET in the chain. */ 75477298Sobrien 75577298Sobrienvoid 75633965Sjdpsymbol_insert (addme, target, rootPP, lastPP) 75733965Sjdp symbolS *addme; 75833965Sjdp symbolS *target; 75933965Sjdp symbolS **rootPP; 76060484Sobrien symbolS **lastPP ATTRIBUTE_UNUSED; 76133965Sjdp{ 76260484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 76360484Sobrien abort (); 76460484Sobrien if (LOCAL_SYMBOL_CHECK (target)) 76560484Sobrien abort (); 76660484Sobrien 76733965Sjdp if (target->sy_previous != NULL) 76833965Sjdp { 76933965Sjdp target->sy_previous->sy_next = addme; 77033965Sjdp } 77133965Sjdp else 77233965Sjdp { 77333965Sjdp know (*rootPP == target); 77433965Sjdp *rootPP = addme; 77577298Sobrien } /* if not first */ 77633965Sjdp 77733965Sjdp addme->sy_previous = target->sy_previous; 77833965Sjdp target->sy_previous = addme; 77933965Sjdp addme->sy_next = target; 78033965Sjdp 78133965Sjdp debug_verify_symchain (*rootPP, *lastPP); 78233965Sjdp} 78333965Sjdp 78433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 78533965Sjdp 78677298Sobrienvoid 78733965Sjdpverify_symbol_chain (rootP, lastP) 78833965Sjdp symbolS *rootP; 78933965Sjdp symbolS *lastP; 79033965Sjdp{ 79133965Sjdp symbolS *symbolP = rootP; 79233965Sjdp 79333965Sjdp if (symbolP == NULL) 79433965Sjdp return; 79533965Sjdp 79633965Sjdp for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) 79733965Sjdp { 79860484Sobrien#ifdef BFD_ASSEMBLER 79960484Sobrien assert (symbolP->bsym != NULL); 80060484Sobrien#endif 80133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 80233965Sjdp assert (symbolP->sy_next->sy_previous == symbolP); 80333965Sjdp#else 80433965Sjdp /* Walk the list anyways, to make sure pointers are still good. */ 80533965Sjdp ; 80633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 80733965Sjdp } 80833965Sjdp 80933965Sjdp assert (lastP == symbolP); 81033965Sjdp} 81133965Sjdp 81233965Sjdpvoid 81333965Sjdpverify_symbol_chain_2 (sym) 81433965Sjdp 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 82633965Sjdp/* Resolve the value of a symbol. This is called during the final 82733965Sjdp pass over the symbol table to resolve any symbols with complex 82833965Sjdp values. */ 82933965Sjdp 83038889SjdpvalueT 83189857Sobrienresolve_symbol_value (symp) 83233965Sjdp symbolS *symp; 83333965Sjdp{ 83433965Sjdp int resolved; 83538889Sjdp valueT final_val; 83638889Sjdp segT final_seg; 83733965Sjdp 83860484Sobrien#ifdef BFD_ASSEMBLER 83960484Sobrien if (LOCAL_SYMBOL_CHECK (symp)) 84060484Sobrien { 84160484Sobrien struct local_symbol *locsym = (struct local_symbol *) symp; 84260484Sobrien 84389857Sobrien final_val = locsym->lsy_value; 84460484Sobrien if (local_symbol_resolved_p (locsym)) 84589857Sobrien return final_val; 84660484Sobrien 84789857Sobrien final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE; 84860484Sobrien 84989857Sobrien if (finalize_syms) 85060484Sobrien { 85189857Sobrien locsym->lsy_value = final_val; 85260484Sobrien local_symbol_mark_resolved (locsym); 85360484Sobrien } 85460484Sobrien 85560484Sobrien return final_val; 85660484Sobrien } 85760484Sobrien#endif 85860484Sobrien 85933965Sjdp if (symp->sy_resolved) 86038889Sjdp { 86138889Sjdp if (symp->sy_value.X_op == O_constant) 86238889Sjdp return (valueT) symp->sy_value.X_add_number; 86338889Sjdp else 86438889Sjdp return 0; 86538889Sjdp } 86633965Sjdp 86733965Sjdp resolved = 0; 86838889Sjdp final_seg = S_GET_SEGMENT (symp); 86933965Sjdp 87033965Sjdp if (symp->sy_resolving) 87133965Sjdp { 87289857Sobrien if (finalize_syms) 87389857Sobrien as_bad (_("symbol definition loop encountered at `%s'"), 87477298Sobrien S_GET_NAME (symp)); 87538889Sjdp final_val = 0; 87633965Sjdp resolved = 1; 87733965Sjdp } 87833965Sjdp else 87933965Sjdp { 88038889Sjdp symbolS *add_symbol, *op_symbol; 88138889Sjdp offsetT left, right; 88233965Sjdp segT seg_left, seg_right; 88338889Sjdp operatorT op; 88433965Sjdp 88533965Sjdp symp->sy_resolving = 1; 88633965Sjdp 88738889Sjdp /* Help out with CSE. */ 88838889Sjdp add_symbol = symp->sy_value.X_add_symbol; 88938889Sjdp op_symbol = symp->sy_value.X_op_symbol; 89038889Sjdp final_val = symp->sy_value.X_add_number; 89138889Sjdp op = symp->sy_value.X_op; 89238889Sjdp 89338889Sjdp switch (op) 89433965Sjdp { 89538889Sjdp default: 89638889Sjdp BAD_CASE (op); 89738889Sjdp break; 89833965Sjdp 89933965Sjdp case O_absent: 90038889Sjdp final_val = 0; 90133965Sjdp /* Fall through. */ 90238889Sjdp 90333965Sjdp case O_constant: 90460484Sobrien final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; 90538889Sjdp if (final_seg == expr_section) 90638889Sjdp final_seg = absolute_section; 90733965Sjdp resolved = 1; 90833965Sjdp break; 90933965Sjdp 91033965Sjdp case O_symbol: 91138889Sjdp case O_symbol_rva: 91289857Sobrien left = resolve_symbol_value (add_symbol); 91389857Sobrien seg_left = S_GET_SEGMENT (add_symbol); 91489857Sobrien if (finalize_syms) 91589857Sobrien symp->sy_value.X_op_symbol = NULL; 91689857Sobrien 91738889Sjdp do_symbol: 91833965Sjdp if (symp->sy_mri_common) 91933965Sjdp { 92033965Sjdp /* This is a symbol inside an MRI common section. The 92189857Sobrien relocation routines are going to handle it specially. 92289857Sobrien Don't change the value. */ 92360484Sobrien resolved = symbol_resolved_p (add_symbol); 92433965Sjdp break; 92533965Sjdp } 92633965Sjdp 92789857Sobrien if (finalize_syms && final_val == 0) 92860484Sobrien { 92960484Sobrien if (LOCAL_SYMBOL_CHECK (add_symbol)) 93060484Sobrien add_symbol = local_symbol_convert ((struct local_symbol *) 93160484Sobrien add_symbol); 93260484Sobrien copy_symbol_attributes (symp, add_symbol); 93360484Sobrien } 93433965Sjdp 93589857Sobrien /* If we have equated this symbol to an undefined or common 93689857Sobrien symbol, keep X_op set to O_symbol, and don't change 93789857Sobrien X_add_number. This permits the routine which writes out 93889857Sobrien relocation to detect this case, and convert the 93989857Sobrien relocation to be against the symbol to which this symbol 94089857Sobrien is equated. */ 94138889Sjdp if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol)) 94233965Sjdp { 94389857Sobrien if (finalize_syms) 94438889Sjdp { 94538889Sjdp symp->sy_value.X_op = O_symbol; 94660484Sobrien symp->sy_value.X_add_symbol = add_symbol; 94738889Sjdp symp->sy_value.X_add_number = final_val; 94889857Sobrien /* Use X_op_symbol as a flag. */ 94989857Sobrien symp->sy_value.X_op_symbol = add_symbol; 95089857Sobrien final_seg = seg_left; 95138889Sjdp } 95238889Sjdp final_val = 0; 95360484Sobrien resolved = symbol_resolved_p (add_symbol); 95489857Sobrien symp->sy_resolving = 0; 95538889Sjdp goto exit_dont_set_value; 95633965Sjdp } 95789857Sobrien else if (finalize_syms && final_seg == expr_section 95889857Sobrien && seg_left != expr_section) 95989857Sobrien { 96089857Sobrien /* If the symbol is an expression symbol, do similarly 96189857Sobrien as for undefined and common syms above. Handles 96289857Sobrien "sym +/- expr" where "expr" cannot be evaluated 96389857Sobrien immediately, and we want relocations to be against 96489857Sobrien "sym", eg. because it is weak. */ 96589857Sobrien symp->sy_value.X_op = O_symbol; 96689857Sobrien symp->sy_value.X_add_symbol = add_symbol; 96789857Sobrien symp->sy_value.X_add_number = final_val; 96889857Sobrien symp->sy_value.X_op_symbol = add_symbol; 96989857Sobrien final_seg = seg_left; 97089857Sobrien final_val += symp->sy_frag->fr_address + left; 97189857Sobrien resolved = symbol_resolved_p (add_symbol); 97289857Sobrien symp->sy_resolving = 0; 97389857Sobrien goto exit_dont_set_value; 97489857Sobrien } 97533965Sjdp else 97633965Sjdp { 97738889Sjdp final_val += symp->sy_frag->fr_address + left; 97838889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 97989857Sobrien final_seg = seg_left; 98033965Sjdp } 98133965Sjdp 98260484Sobrien resolved = symbol_resolved_p (add_symbol); 98333965Sjdp break; 98433965Sjdp 98533965Sjdp case O_uminus: 98633965Sjdp case O_bit_not: 98733965Sjdp case O_logical_not: 98889857Sobrien left = resolve_symbol_value (add_symbol); 98938889Sjdp 99038889Sjdp if (op == O_uminus) 99138889Sjdp left = -left; 99238889Sjdp else if (op == O_logical_not) 99338889Sjdp left = !left; 99433965Sjdp else 99538889Sjdp left = ~left; 99638889Sjdp 99738889Sjdp final_val += left + symp->sy_frag->fr_address; 99838889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 99938889Sjdp final_seg = absolute_section; 100038889Sjdp 100160484Sobrien resolved = symbol_resolved_p (add_symbol); 100233965Sjdp break; 100333965Sjdp 100433965Sjdp case O_multiply: 100533965Sjdp case O_divide: 100633965Sjdp case O_modulus: 100733965Sjdp case O_left_shift: 100833965Sjdp case O_right_shift: 100933965Sjdp case O_bit_inclusive_or: 101033965Sjdp case O_bit_or_not: 101133965Sjdp case O_bit_exclusive_or: 101233965Sjdp case O_bit_and: 101333965Sjdp case O_add: 101433965Sjdp case O_subtract: 101533965Sjdp case O_eq: 101633965Sjdp case O_ne: 101733965Sjdp case O_lt: 101833965Sjdp case O_le: 101933965Sjdp case O_ge: 102033965Sjdp case O_gt: 102133965Sjdp case O_logical_and: 102233965Sjdp case O_logical_or: 102389857Sobrien left = resolve_symbol_value (add_symbol); 102489857Sobrien right = resolve_symbol_value (op_symbol); 102538889Sjdp seg_left = S_GET_SEGMENT (add_symbol); 102638889Sjdp seg_right = S_GET_SEGMENT (op_symbol); 102733965Sjdp 102838889Sjdp /* Simplify addition or subtraction of a constant by folding the 102938889Sjdp constant into X_add_number. */ 103089857Sobrien if (op == O_add) 103138889Sjdp { 103238889Sjdp if (seg_right == absolute_section) 103338889Sjdp { 103489857Sobrien final_val += right; 103538889Sjdp goto do_symbol; 103638889Sjdp } 103789857Sobrien else if (seg_left == absolute_section) 103838889Sjdp { 103938889Sjdp final_val += left; 104038889Sjdp add_symbol = op_symbol; 104138889Sjdp left = right; 104289857Sobrien seg_left = seg_right; 104338889Sjdp goto do_symbol; 104438889Sjdp } 104538889Sjdp } 104689857Sobrien else if (op == O_subtract) 104789857Sobrien { 104889857Sobrien if (seg_right == absolute_section) 104989857Sobrien { 105089857Sobrien final_val -= right; 105189857Sobrien goto do_symbol; 105289857Sobrien } 105389857Sobrien } 105438889Sjdp 105589857Sobrien /* Equality and non-equality tests are permitted on anything. 105689857Sobrien Subtraction, and other comparison operators are permitted if 105789857Sobrien both operands are in the same section. Otherwise, both 105889857Sobrien operands must be absolute. We already handled the case of 105989857Sobrien addition or subtraction of a constant above. This will 106089857Sobrien probably need to be changed for an object file format which 106189857Sobrien supports arbitrary expressions, such as IEEE-695. 106289857Sobrien 106389857Sobrien Don't emit messages unless we're finalizing the symbol value, 106438889Sjdp otherwise we may get the same message multiple times. */ 106589857Sobrien if (op != O_eq && op != O_ne 106689857Sobrien && (seg_left != absolute_section 106789857Sobrien || seg_right != absolute_section) 106889857Sobrien && ((op != O_subtract 106989857Sobrien && op != O_lt && op != O_le && op != O_ge && op != O_gt) 107060484Sobrien || seg_left != seg_right 107189857Sobrien || (seg_left == undefined_section 107289857Sobrien && add_symbol != op_symbol)) 107389857Sobrien && finalize_syms) 107433965Sjdp { 107533965Sjdp char *file; 107633965Sjdp unsigned int line; 107733965Sjdp 107833965Sjdp if (expr_symbol_where (symp, &file, &line)) 107933965Sjdp { 108033965Sjdp if (seg_left == undefined_section) 108133965Sjdp as_bad_where (file, line, 108289857Sobrien _("undefined symbol `%s' in operation"), 108333965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol)); 108433965Sjdp if (seg_right == undefined_section) 108533965Sjdp as_bad_where (file, line, 108689857Sobrien _("undefined symbol `%s' in operation"), 108733965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol)); 108833965Sjdp if (seg_left != undefined_section 108933965Sjdp && seg_right != undefined_section) 109077298Sobrien as_bad_where (file, line, 109177298Sobrien _("invalid section for operation")); 109233965Sjdp } 109333965Sjdp else 109433965Sjdp { 109533965Sjdp if (seg_left == undefined_section) 109689857Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 109733965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol), 109833965Sjdp S_GET_NAME (symp)); 109933965Sjdp if (seg_right == undefined_section) 110089857Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 110133965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol), 110233965Sjdp S_GET_NAME (symp)); 110333965Sjdp if (seg_left != undefined_section 110433965Sjdp && seg_right != undefined_section) 110589857Sobrien as_bad (_("invalid section for operation setting `%s'"), 110633965Sjdp S_GET_NAME (symp)); 110733965Sjdp } 110833965Sjdp } 110933965Sjdp 111038889Sjdp /* Check for division by zero. */ 111138889Sjdp if ((op == O_divide || op == O_modulus) && right == 0) 111238889Sjdp { 111338889Sjdp /* If seg_right is not absolute_section, then we've 111489857Sobrien already issued a warning about using a bad symbol. */ 111589857Sobrien if (seg_right == absolute_section && finalize_syms) 111638889Sjdp { 111738889Sjdp char *file; 111838889Sjdp unsigned int line; 111938889Sjdp 112038889Sjdp if (expr_symbol_where (symp, &file, &line)) 112160484Sobrien as_bad_where (file, line, _("division by zero")); 112238889Sjdp else 112389857Sobrien as_bad (_("division by zero when setting `%s'"), 112438889Sjdp S_GET_NAME (symp)); 112538889Sjdp } 112638889Sjdp 112738889Sjdp right = 1; 112838889Sjdp } 112938889Sjdp 113033965Sjdp switch (symp->sy_value.X_op) 113133965Sjdp { 113238889Sjdp case O_multiply: left *= right; break; 113338889Sjdp case O_divide: left /= right; break; 113438889Sjdp case O_modulus: left %= right; break; 113538889Sjdp case O_left_shift: left <<= right; break; 113638889Sjdp case O_right_shift: left >>= right; break; 113738889Sjdp case O_bit_inclusive_or: left |= right; break; 113838889Sjdp case O_bit_or_not: left |= ~right; break; 113938889Sjdp case O_bit_exclusive_or: left ^= right; break; 114038889Sjdp case O_bit_and: left &= right; break; 114138889Sjdp case O_add: left += right; break; 114238889Sjdp case O_subtract: left -= right; break; 114389857Sobrien case O_eq: 114489857Sobrien case O_ne: 114589857Sobrien left = (left == right && seg_left == seg_right 114689857Sobrien && (seg_left != undefined_section 114789857Sobrien || add_symbol == op_symbol) 114889857Sobrien ? ~ (offsetT) 0 : 0); 114989857Sobrien if (symp->sy_value.X_op == O_ne) 115089857Sobrien left = ~left; 115189857Sobrien break; 115238889Sjdp case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; 115338889Sjdp case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; 115438889Sjdp case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; 115538889Sjdp case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; 115638889Sjdp case O_logical_and: left = left && right; break; 115738889Sjdp case O_logical_or: left = left || right; break; 115838889Sjdp default: abort (); 115933965Sjdp } 116038889Sjdp 116138889Sjdp final_val += symp->sy_frag->fr_address + left; 116238889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 116338889Sjdp final_seg = absolute_section; 116460484Sobrien resolved = (symbol_resolved_p (add_symbol) 116560484Sobrien && symbol_resolved_p (op_symbol)); 116677298Sobrien break; 116733965Sjdp 116833965Sjdp case O_register: 116933965Sjdp case O_big: 117033965Sjdp case O_illegal: 117133965Sjdp /* Give an error (below) if not in expr_section. We don't 117233965Sjdp want to worry about expr_section symbols, because they 117333965Sjdp are fictional (they are created as part of expression 117433965Sjdp resolution), and any problems may not actually mean 117533965Sjdp anything. */ 117633965Sjdp break; 117733965Sjdp } 117838889Sjdp 117938889Sjdp symp->sy_resolving = 0; 118033965Sjdp } 118133965Sjdp 118289857Sobrien if (finalize_syms) 118389857Sobrien S_SET_VALUE (symp, final_val); 118438889Sjdp 118589857Sobrienexit_dont_set_value: 118689857Sobrien /* Always set the segment, even if not finalizing the value. 118789857Sobrien The segment is used to determine whether a symbol is defined. */ 118838889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER) 118989857Sobrien /* The old a.out backend does not handle S_SET_SEGMENT correctly 119089857Sobrien for a stab symbol, so we use this bad hack. */ 119189857Sobrien if (final_seg != S_GET_SEGMENT (symp)) 119238889Sjdp#endif 119389857Sobrien S_SET_SEGMENT (symp, final_seg); 119438889Sjdp 119533965Sjdp /* Don't worry if we can't resolve an expr_section symbol. */ 119689857Sobrien if (finalize_syms) 119733965Sjdp { 119838889Sjdp if (resolved) 119938889Sjdp symp->sy_resolved = 1; 120038889Sjdp else if (S_GET_SEGMENT (symp) != expr_section) 120138889Sjdp { 120289857Sobrien as_bad (_("can't resolve value for symbol `%s'"), 120377298Sobrien S_GET_NAME (symp)); 120438889Sjdp symp->sy_resolved = 1; 120538889Sjdp } 120633965Sjdp } 120738889Sjdp 120838889Sjdp return final_val; 120933965Sjdp} 121033965Sjdp 121160484Sobrien#ifdef BFD_ASSEMBLER 121260484Sobrien 121360484Sobrienstatic void resolve_local_symbol PARAMS ((const char *, PTR)); 121460484Sobrien 121560484Sobrien/* A static function passed to hash_traverse. */ 121660484Sobrien 121760484Sobrienstatic void 121860484Sobrienresolve_local_symbol (key, value) 121960484Sobrien const char *key ATTRIBUTE_UNUSED; 122060484Sobrien PTR value; 122160484Sobrien{ 122260484Sobrien if (value != NULL) 122389857Sobrien resolve_symbol_value (value); 122460484Sobrien} 122560484Sobrien 122660484Sobrien#endif 122760484Sobrien 122860484Sobrien/* Resolve all local symbols. */ 122960484Sobrien 123060484Sobrienvoid 123160484Sobrienresolve_local_symbol_values () 123260484Sobrien{ 123360484Sobrien#ifdef BFD_ASSEMBLER 123460484Sobrien hash_traverse (local_hash, resolve_local_symbol); 123560484Sobrien#endif 123660484Sobrien} 123760484Sobrien 123833965Sjdp/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". 123933965Sjdp They are *really* local. That is, they go out of scope whenever we see a 124033965Sjdp label that isn't local. Also, like fb labels, there can be multiple 124133965Sjdp instances of a dollar label. Therefor, we name encode each instance with 124233965Sjdp the instance number, keep a list of defined symbols separate from the real 124333965Sjdp symbol table, and we treat these buggers as a sparse array. */ 124433965Sjdp 124533965Sjdpstatic long *dollar_labels; 124633965Sjdpstatic long *dollar_label_instances; 124733965Sjdpstatic char *dollar_label_defines; 124838889Sjdpstatic unsigned long dollar_label_count; 124933965Sjdpstatic unsigned long dollar_label_max; 125033965Sjdp 125177298Sobrienint 125233965Sjdpdollar_label_defined (label) 125333965Sjdp long label; 125433965Sjdp{ 125533965Sjdp long *i; 125633965Sjdp 125733965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 125833965Sjdp 125933965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 126033965Sjdp if (*i == label) 126133965Sjdp return dollar_label_defines[i - dollar_labels]; 126233965Sjdp 126377298Sobrien /* If we get here, label isn't defined. */ 126433965Sjdp return 0; 126577298Sobrien} 126633965Sjdp 126733965Sjdpstatic long 126833965Sjdpdollar_label_instance (label) 126933965Sjdp long label; 127033965Sjdp{ 127133965Sjdp long *i; 127233965Sjdp 127333965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 127433965Sjdp 127533965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 127633965Sjdp if (*i == label) 127733965Sjdp return (dollar_label_instances[i - dollar_labels]); 127833965Sjdp 127977298Sobrien /* If we get here, we haven't seen the label before. 128077298Sobrien Therefore its instance count is zero. */ 128133965Sjdp return 0; 128233965Sjdp} 128333965Sjdp 128477298Sobrienvoid 128533965Sjdpdollar_label_clear () 128633965Sjdp{ 128733965Sjdp memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count); 128833965Sjdp} 128933965Sjdp 129033965Sjdp#define DOLLAR_LABEL_BUMP_BY 10 129133965Sjdp 129277298Sobrienvoid 129333965Sjdpdefine_dollar_label (label) 129433965Sjdp long label; 129533965Sjdp{ 129633965Sjdp long *i; 129733965Sjdp 129833965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 129933965Sjdp if (*i == label) 130033965Sjdp { 130133965Sjdp ++dollar_label_instances[i - dollar_labels]; 130233965Sjdp dollar_label_defines[i - dollar_labels] = 1; 130333965Sjdp return; 130433965Sjdp } 130533965Sjdp 130677298Sobrien /* If we get to here, we don't have label listed yet. */ 130733965Sjdp 130833965Sjdp if (dollar_labels == NULL) 130933965Sjdp { 131033965Sjdp dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 131133965Sjdp dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 131233965Sjdp dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY); 131333965Sjdp dollar_label_max = DOLLAR_LABEL_BUMP_BY; 131433965Sjdp dollar_label_count = 0; 131533965Sjdp } 131633965Sjdp else if (dollar_label_count == dollar_label_max) 131733965Sjdp { 131833965Sjdp dollar_label_max += DOLLAR_LABEL_BUMP_BY; 131933965Sjdp dollar_labels = (long *) xrealloc ((char *) dollar_labels, 132033965Sjdp dollar_label_max * sizeof (long)); 132133965Sjdp dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances, 132233965Sjdp dollar_label_max * sizeof (long)); 132333965Sjdp dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max); 132477298Sobrien } /* if we needed to grow */ 132533965Sjdp 132633965Sjdp dollar_labels[dollar_label_count] = label; 132733965Sjdp dollar_label_instances[dollar_label_count] = 1; 132833965Sjdp dollar_label_defines[dollar_label_count] = 1; 132933965Sjdp ++dollar_label_count; 133033965Sjdp} 133133965Sjdp 133277298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 133333965Sjdp 133477298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Am" 133577298Sobrien where n is the label number and m is the instance number. "L" makes 133677298Sobrien it a label discarded unless debugging and "^A"('\1') ensures no 133777298Sobrien ordinary symbol SHOULD get the same name as a local label 133877298Sobrien symbol. The first "4:" is "L4^A1" - the m numbers begin at 1. 133977298Sobrien 134077298Sobrien fb labels get the same treatment, except that ^B is used in place 134177298Sobrien of ^A. */ 134277298Sobrien 134377298Sobrienchar * /* Return local label name. */ 134433965Sjdpdollar_label_name (n, augend) 134577298Sobrien register long n; /* we just saw "n$:" : n a number. */ 134677298Sobrien register int augend; /* 0 for current instance, 1 for new instance. */ 134733965Sjdp{ 134833965Sjdp long i; 134977298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 135033965Sjdp static char symbol_name_build[24]; 135133965Sjdp register char *p; 135233965Sjdp register char *q; 135377298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 135433965Sjdp 135533965Sjdp know (n >= 0); 135633965Sjdp know (augend == 0 || augend == 1); 135733965Sjdp p = symbol_name_build; 135860484Sobrien#ifdef LOCAL_LABEL_PREFIX 135960484Sobrien *p++ = LOCAL_LABEL_PREFIX; 136060484Sobrien#endif 136133965Sjdp *p++ = 'L'; 136233965Sjdp 136377298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 136477298Sobrien /* Label number. */ 136533965Sjdp q = symbol_name_temporary; 136633965Sjdp for (*q++ = 0, i = n; i; ++q) 136733965Sjdp { 136833965Sjdp *q = i % 10 + '0'; 136933965Sjdp i /= 10; 137033965Sjdp } 137133965Sjdp while ((*p = *--q) != '\0') 137233965Sjdp ++p; 137333965Sjdp 137477298Sobrien *p++ = DOLLAR_LABEL_CHAR; /* ^A */ 137533965Sjdp 137677298Sobrien /* Instance number. */ 137733965Sjdp q = symbol_name_temporary; 137833965Sjdp for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q) 137933965Sjdp { 138033965Sjdp *q = i % 10 + '0'; 138133965Sjdp i /= 10; 138233965Sjdp } 138333965Sjdp while ((*p++ = *--q) != '\0');; 138433965Sjdp 138577298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 138633965Sjdp return symbol_name_build; 138733965Sjdp} 138833965Sjdp 138977298Sobrien/* Sombody else's idea of local labels. They are made by "n:" where n 139077298Sobrien is any decimal digit. Refer to them with 139177298Sobrien "nb" for previous (backward) n: 139277298Sobrien or "nf" for next (forward) n:. 139333965Sjdp 139477298Sobrien We do a little better and let n be any number, not just a single digit, but 139577298Sobrien since the other guy's assembler only does ten, we treat the first ten 139677298Sobrien specially. 139777298Sobrien 139877298Sobrien Like someone else's assembler, we have one set of local label counters for 139977298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 140077298Sobrien implies that one can refer to a label in another segment, and indeed some 140177298Sobrien crufty compilers have done just that. 140277298Sobrien 140377298Sobrien Since there could be a LOT of these things, treat them as a sparse 140477298Sobrien array. */ 140577298Sobrien 140633965Sjdp#define FB_LABEL_SPECIAL (10) 140733965Sjdp 140833965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 140933965Sjdpstatic long *fb_labels; 141033965Sjdpstatic long *fb_label_instances; 141133965Sjdpstatic long fb_label_count; 141233965Sjdpstatic long fb_label_max; 141333965Sjdp 141477298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 141533965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 141633965Sjdp 141777298Sobrienstatic void 141833965Sjdpfb_label_init () 141933965Sjdp{ 142033965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 142177298Sobrien} 142233965Sjdp 142377298Sobrien/* Add one to the instance number of this fb label. */ 142477298Sobrien 142577298Sobrienvoid 142633965Sjdpfb_label_instance_inc (label) 142733965Sjdp long label; 142833965Sjdp{ 142933965Sjdp long *i; 143033965Sjdp 143133965Sjdp if (label < FB_LABEL_SPECIAL) 143233965Sjdp { 143333965Sjdp ++fb_low_counter[label]; 143433965Sjdp return; 143533965Sjdp } 143633965Sjdp 143733965Sjdp if (fb_labels != NULL) 143833965Sjdp { 143933965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 144033965Sjdp i < fb_labels + fb_label_count; ++i) 144133965Sjdp { 144233965Sjdp if (*i == label) 144333965Sjdp { 144433965Sjdp ++fb_label_instances[i - fb_labels]; 144533965Sjdp return; 144677298Sobrien } /* if we find it */ 144777298Sobrien } /* for each existing label */ 144833965Sjdp } 144933965Sjdp 145077298Sobrien /* If we get to here, we don't have label listed yet. */ 145133965Sjdp 145233965Sjdp if (fb_labels == NULL) 145333965Sjdp { 145433965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 145533965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 145633965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 145733965Sjdp fb_label_count = FB_LABEL_SPECIAL; 145833965Sjdp 145933965Sjdp } 146033965Sjdp else if (fb_label_count == fb_label_max) 146133965Sjdp { 146233965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 146333965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 146433965Sjdp fb_label_max * sizeof (long)); 146533965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 146633965Sjdp fb_label_max * sizeof (long)); 146777298Sobrien } /* if we needed to grow */ 146833965Sjdp 146933965Sjdp fb_labels[fb_label_count] = label; 147033965Sjdp fb_label_instances[fb_label_count] = 1; 147133965Sjdp ++fb_label_count; 147233965Sjdp} 147333965Sjdp 147477298Sobrienstatic long 147533965Sjdpfb_label_instance (label) 147633965Sjdp long label; 147733965Sjdp{ 147833965Sjdp long *i; 147933965Sjdp 148033965Sjdp if (label < FB_LABEL_SPECIAL) 148133965Sjdp { 148233965Sjdp return (fb_low_counter[label]); 148333965Sjdp } 148433965Sjdp 148533965Sjdp if (fb_labels != NULL) 148633965Sjdp { 148733965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 148833965Sjdp i < fb_labels + fb_label_count; ++i) 148933965Sjdp { 149033965Sjdp if (*i == label) 149133965Sjdp { 149233965Sjdp return (fb_label_instances[i - fb_labels]); 149377298Sobrien } /* if we find it */ 149477298Sobrien } /* for each existing label */ 149533965Sjdp } 149633965Sjdp 149733965Sjdp /* We didn't find the label, so this must be a reference to the 149833965Sjdp first instance. */ 149933965Sjdp return 0; 150033965Sjdp} 150133965Sjdp 150277298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 150333965Sjdp 150477298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 150577298Sobrien where n is the label number and m is the instance number. "L" makes 150677298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 150777298Sobrien ordinary symbol SHOULD get the same name as a local label 150877298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 150977298Sobrien 151077298Sobrien dollar labels get the same treatment, except that ^A is used in 151177298Sobrien place of ^B. */ 151277298Sobrien 151377298Sobrienchar * /* Return local label name. */ 151433965Sjdpfb_label_name (n, augend) 151577298Sobrien long n; /* We just saw "n:", "nf" or "nb" : n a number. */ 151677298Sobrien long augend; /* 0 for nb, 1 for n:, nf. */ 151733965Sjdp{ 151833965Sjdp long i; 151977298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 152033965Sjdp static char symbol_name_build[24]; 152133965Sjdp register char *p; 152233965Sjdp register char *q; 152377298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 152433965Sjdp 152533965Sjdp know (n >= 0); 152633965Sjdp know (augend == 0 || augend == 1); 152733965Sjdp p = symbol_name_build; 152877298Sobrien#ifdef LOCAL_LABEL_PREFIX 152977298Sobrien *p++ = LOCAL_LABEL_PREFIX; 153077298Sobrien#endif 153133965Sjdp *p++ = 'L'; 153233965Sjdp 153377298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 153477298Sobrien /* Label number. */ 153533965Sjdp q = symbol_name_temporary; 153633965Sjdp for (*q++ = 0, i = n; i; ++q) 153733965Sjdp { 153833965Sjdp *q = i % 10 + '0'; 153933965Sjdp i /= 10; 154033965Sjdp } 154133965Sjdp while ((*p = *--q) != '\0') 154233965Sjdp ++p; 154333965Sjdp 154477298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 154533965Sjdp 154677298Sobrien /* Instance number. */ 154733965Sjdp q = symbol_name_temporary; 154833965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 154933965Sjdp { 155033965Sjdp *q = i % 10 + '0'; 155133965Sjdp i /= 10; 155233965Sjdp } 155333965Sjdp while ((*p++ = *--q) != '\0');; 155433965Sjdp 155577298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 155633965Sjdp return (symbol_name_build); 155777298Sobrien} 155833965Sjdp 155977298Sobrien/* Decode name that may have been generated by foo_label_name() above. 156077298Sobrien If the name wasn't generated by foo_label_name(), then return it 156177298Sobrien unaltered. This is used for error messages. */ 156233965Sjdp 156333965Sjdpchar * 156433965Sjdpdecode_local_label_name (s) 156533965Sjdp char *s; 156633965Sjdp{ 156733965Sjdp char *p; 156833965Sjdp char *symbol_decode; 156933965Sjdp int label_number; 157033965Sjdp int instance_number; 157133965Sjdp char *type; 157278828Sobrien const char *message_format; 157377298Sobrien int index = 0; 157433965Sjdp 157577298Sobrien#ifdef LOCAL_LABEL_PREFIX 157677298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 157777298Sobrien ++index; 157877298Sobrien#endif 157977298Sobrien 158077298Sobrien if (s[index] != 'L') 158133965Sjdp return s; 158233965Sjdp 158389857Sobrien for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p) 158433965Sjdp label_number = (10 * label_number) + *p - '0'; 158533965Sjdp 158677298Sobrien if (*p == DOLLAR_LABEL_CHAR) 158733965Sjdp type = "dollar"; 158877298Sobrien else if (*p == LOCAL_LABEL_CHAR) 158933965Sjdp type = "fb"; 159033965Sjdp else 159133965Sjdp return s; 159233965Sjdp 159389857Sobrien for (instance_number = 0, p++; ISDIGIT (*p); ++p) 159433965Sjdp instance_number = (10 * instance_number) + *p - '0'; 159533965Sjdp 159678828Sobrien message_format = _("\"%d\" (instance number %d of a %s label)"); 159733965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 159833965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 159933965Sjdp 160033965Sjdp return symbol_decode; 160133965Sjdp} 160233965Sjdp 160333965Sjdp/* Get the value of a symbol. */ 160433965Sjdp 160533965SjdpvalueT 160633965SjdpS_GET_VALUE (s) 160733965Sjdp symbolS *s; 160833965Sjdp{ 160960484Sobrien#ifdef BFD_ASSEMBLER 161060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 161189857Sobrien return resolve_symbol_value (s); 161260484Sobrien#endif 161360484Sobrien 161489857Sobrien if (!s->sy_resolved) 161589857Sobrien { 161689857Sobrien valueT val = resolve_symbol_value (s); 161789857Sobrien if (!finalize_syms) 161889857Sobrien return val; 161989857Sobrien } 162033965Sjdp if (s->sy_value.X_op != O_constant) 162133965Sjdp { 162233965Sjdp static symbolS *recur; 162333965Sjdp 162433965Sjdp /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON 162533965Sjdp may call S_GET_VALUE. We use a static symbol to avoid the 162633965Sjdp immediate recursion. */ 162733965Sjdp if (recur == s) 162833965Sjdp return (valueT) s->sy_value.X_add_number; 162933965Sjdp recur = s; 163033965Sjdp if (! s->sy_resolved 163133965Sjdp || s->sy_value.X_op != O_symbol 163233965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 163389857Sobrien as_bad (_("attempt to get value of unresolved symbol `%s'"), 163433965Sjdp S_GET_NAME (s)); 163533965Sjdp recur = NULL; 163633965Sjdp } 163733965Sjdp return (valueT) s->sy_value.X_add_number; 163833965Sjdp} 163933965Sjdp 164033965Sjdp/* Set the value of a symbol. */ 164133965Sjdp 164233965Sjdpvoid 164333965SjdpS_SET_VALUE (s, val) 164433965Sjdp symbolS *s; 164533965Sjdp valueT val; 164633965Sjdp{ 164760484Sobrien#ifdef BFD_ASSEMBLER 164860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 164960484Sobrien { 165089857Sobrien ((struct local_symbol *) s)->lsy_value = val; 165160484Sobrien return; 165260484Sobrien } 165360484Sobrien#endif 165460484Sobrien 165533965Sjdp s->sy_value.X_op = O_constant; 165633965Sjdp s->sy_value.X_add_number = (offsetT) val; 165733965Sjdp s->sy_value.X_unsigned = 0; 165833965Sjdp} 165933965Sjdp 166033965Sjdpvoid 166133965Sjdpcopy_symbol_attributes (dest, src) 166233965Sjdp symbolS *dest, *src; 166333965Sjdp{ 166460484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 166560484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 166660484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 166760484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 166860484Sobrien 166933965Sjdp#ifdef BFD_ASSEMBLER 167033965Sjdp /* In an expression, transfer the settings of these flags. 167133965Sjdp The user can override later, of course. */ 167238889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 167333965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 167433965Sjdp#endif 167533965Sjdp 167633965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 167733965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 167833965Sjdp#endif 167933965Sjdp} 168033965Sjdp 168133965Sjdp#ifdef BFD_ASSEMBLER 168233965Sjdp 168333965Sjdpint 168460484SobrienS_IS_FUNCTION (s) 168560484Sobrien symbolS *s; 168660484Sobrien{ 168760484Sobrien flagword flags; 168860484Sobrien 168960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 169060484Sobrien return 0; 169160484Sobrien 169260484Sobrien flags = s->bsym->flags; 169360484Sobrien 169460484Sobrien return (flags & BSF_FUNCTION) != 0; 169560484Sobrien} 169660484Sobrien 169760484Sobrienint 169833965SjdpS_IS_EXTERNAL (s) 169933965Sjdp symbolS *s; 170033965Sjdp{ 170160484Sobrien flagword flags; 170233965Sjdp 170360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 170460484Sobrien return 0; 170560484Sobrien 170660484Sobrien flags = s->bsym->flags; 170760484Sobrien 170877298Sobrien /* Sanity check. */ 170938889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 171033965Sjdp abort (); 171133965Sjdp 171233965Sjdp return (flags & BSF_GLOBAL) != 0; 171333965Sjdp} 171433965Sjdp 171533965Sjdpint 171633965SjdpS_IS_WEAK (s) 171733965Sjdp symbolS *s; 171833965Sjdp{ 171960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 172060484Sobrien return 0; 172133965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 172233965Sjdp} 172333965Sjdp 172433965Sjdpint 172533965SjdpS_IS_COMMON (s) 172633965Sjdp symbolS *s; 172733965Sjdp{ 172860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 172960484Sobrien return 0; 173033965Sjdp return bfd_is_com_section (s->bsym->section); 173133965Sjdp} 173233965Sjdp 173333965Sjdpint 173433965SjdpS_IS_DEFINED (s) 173533965Sjdp symbolS *s; 173633965Sjdp{ 173760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 173860484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 173933965Sjdp return s->bsym->section != undefined_section; 174033965Sjdp} 174133965Sjdp 174233965Sjdpint 174333965SjdpS_IS_DEBUG (s) 174433965Sjdp symbolS *s; 174533965Sjdp{ 174660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 174760484Sobrien return 0; 174833965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 174933965Sjdp return 1; 175033965Sjdp return 0; 175133965Sjdp} 175233965Sjdp 175333965Sjdpint 175433965SjdpS_IS_LOCAL (s) 175533965Sjdp symbolS *s; 175633965Sjdp{ 175760484Sobrien flagword flags; 175833965Sjdp const char *name; 175933965Sjdp 176060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 176160484Sobrien return 1; 176260484Sobrien 176360484Sobrien flags = s->bsym->flags; 176460484Sobrien 176577298Sobrien /* Sanity check. */ 176638889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 176733965Sjdp abort (); 176833965Sjdp 176933965Sjdp if (bfd_get_section (s->bsym) == reg_section) 177033965Sjdp return 1; 177133965Sjdp 177238889Sjdp if (flag_strip_local_absolute 177338889Sjdp && (flags & BSF_GLOBAL) == 0 177438889Sjdp && bfd_get_section (s->bsym) == absolute_section) 177538889Sjdp return 1; 177638889Sjdp 177733965Sjdp name = S_GET_NAME (s); 177833965Sjdp return (name != NULL 177933965Sjdp && ! S_IS_DEBUG (s) 178077298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 178177298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 178233965Sjdp || (! flag_keep_locals 178333965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 178433965Sjdp || (flag_mri 178533965Sjdp && name[0] == '?' 178633965Sjdp && name[1] == '?'))))); 178733965Sjdp} 178833965Sjdp 178933965Sjdpint 179033965SjdpS_IS_EXTERN (s) 179133965Sjdp symbolS *s; 179233965Sjdp{ 179333965Sjdp return S_IS_EXTERNAL (s); 179433965Sjdp} 179533965Sjdp 179633965Sjdpint 179733965SjdpS_IS_STABD (s) 179833965Sjdp symbolS *s; 179933965Sjdp{ 180033965Sjdp return S_GET_NAME (s) == 0; 180133965Sjdp} 180233965Sjdp 180333965SjdpCONST char * 180433965SjdpS_GET_NAME (s) 180533965Sjdp symbolS *s; 180633965Sjdp{ 180760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 180860484Sobrien return ((struct local_symbol *) s)->lsy_name; 180933965Sjdp return s->bsym->name; 181033965Sjdp} 181133965Sjdp 181233965SjdpsegT 181333965SjdpS_GET_SEGMENT (s) 181433965Sjdp symbolS *s; 181533965Sjdp{ 181660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 181760484Sobrien return ((struct local_symbol *) s)->lsy_section; 181833965Sjdp return s->bsym->section; 181933965Sjdp} 182033965Sjdp 182133965Sjdpvoid 182233965SjdpS_SET_SEGMENT (s, seg) 182333965Sjdp symbolS *s; 182433965Sjdp segT seg; 182533965Sjdp{ 182638889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 182738889Sjdp faults assigning back to const global symbols such as *ABS*, but it 182838889Sjdp shouldn't happen anyway. */ 182938889Sjdp 183060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 183160484Sobrien { 183260484Sobrien if (seg == reg_section) 183360484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 183460484Sobrien else 183560484Sobrien { 183660484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 183760484Sobrien return; 183860484Sobrien } 183960484Sobrien } 184060484Sobrien 184138889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 184238889Sjdp { 184338889Sjdp if (s->bsym->section != seg) 184477298Sobrien abort (); 184538889Sjdp } 184638889Sjdp else 184738889Sjdp s->bsym->section = seg; 184833965Sjdp} 184933965Sjdp 185033965Sjdpvoid 185133965SjdpS_SET_EXTERNAL (s) 185233965Sjdp symbolS *s; 185333965Sjdp{ 185460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 185560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 185633965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 185733965Sjdp { 185833965Sjdp /* Let .weak override .global. */ 185933965Sjdp return; 186033965Sjdp } 186178828Sobrien if (s->bsym->flags & BSF_SECTION_SYM) 186278828Sobrien { 186378828Sobrien char * file; 186478828Sobrien unsigned int line; 186578828Sobrien 186678828Sobrien /* Do not reassign section symbols. */ 186778828Sobrien as_where (& file, & line); 186878828Sobrien as_warn_where (file, line, 186989857Sobrien _("section symbols are already global")); 187078828Sobrien return; 187178828Sobrien } 187233965Sjdp s->bsym->flags |= BSF_GLOBAL; 187377298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 187433965Sjdp} 187533965Sjdp 187633965Sjdpvoid 187733965SjdpS_CLEAR_EXTERNAL (s) 187833965Sjdp symbolS *s; 187933965Sjdp{ 188060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 188160484Sobrien return; 188233965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 188333965Sjdp { 188433965Sjdp /* Let .weak override. */ 188533965Sjdp return; 188633965Sjdp } 188733965Sjdp s->bsym->flags |= BSF_LOCAL; 188877298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 188933965Sjdp} 189033965Sjdp 189133965Sjdpvoid 189233965SjdpS_SET_WEAK (s) 189333965Sjdp symbolS *s; 189433965Sjdp{ 189560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 189660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 189733965Sjdp s->bsym->flags |= BSF_WEAK; 189877298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 189933965Sjdp} 190033965Sjdp 190133965Sjdpvoid 190233965SjdpS_SET_NAME (s, name) 190333965Sjdp symbolS *s; 190433965Sjdp char *name; 190533965Sjdp{ 190660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 190760484Sobrien { 190860484Sobrien ((struct local_symbol *) s)->lsy_name = name; 190960484Sobrien return; 191060484Sobrien } 191133965Sjdp s->bsym->name = name; 191233965Sjdp} 191333965Sjdp#endif /* BFD_ASSEMBLER */ 191433965Sjdp 191560484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS 191660484Sobrien 191760484Sobrien/* Return the previous symbol in a chain. */ 191860484Sobrien 191960484SobriensymbolS * 192060484Sobriensymbol_previous (s) 192160484Sobrien symbolS *s; 192260484Sobrien{ 192360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 192460484Sobrien abort (); 192560484Sobrien return s->sy_previous; 192660484Sobrien} 192760484Sobrien 192860484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */ 192960484Sobrien 193060484Sobrien/* Return the next symbol in a chain. */ 193160484Sobrien 193260484SobriensymbolS * 193360484Sobriensymbol_next (s) 193460484Sobrien symbolS *s; 193560484Sobrien{ 193660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 193760484Sobrien abort (); 193860484Sobrien return s->sy_next; 193960484Sobrien} 194060484Sobrien 194160484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 194260484Sobrien 194360484SobrienexpressionS * 194460484Sobriensymbol_get_value_expression (s) 194560484Sobrien symbolS *s; 194660484Sobrien{ 194760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 194860484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 194960484Sobrien return &s->sy_value; 195060484Sobrien} 195160484Sobrien 195260484Sobrien/* Set the value of a symbol to an expression. */ 195360484Sobrien 195433965Sjdpvoid 195560484Sobriensymbol_set_value_expression (s, exp) 195660484Sobrien symbolS *s; 195760484Sobrien const expressionS *exp; 195860484Sobrien{ 195960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 196060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 196160484Sobrien s->sy_value = *exp; 196260484Sobrien} 196360484Sobrien 196460484Sobrien/* Set the frag of a symbol. */ 196560484Sobrien 196660484Sobrienvoid 196760484Sobriensymbol_set_frag (s, f) 196860484Sobrien symbolS *s; 196960484Sobrien fragS *f; 197060484Sobrien{ 197160484Sobrien#ifdef BFD_ASSEMBLER 197260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197360484Sobrien { 197460484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 197560484Sobrien return; 197660484Sobrien } 197760484Sobrien#endif 197860484Sobrien s->sy_frag = f; 197960484Sobrien} 198060484Sobrien 198160484Sobrien/* Return the frag of a symbol. */ 198260484Sobrien 198360484SobrienfragS * 198460484Sobriensymbol_get_frag (s) 198560484Sobrien symbolS *s; 198660484Sobrien{ 198760484Sobrien#ifdef BFD_ASSEMBLER 198860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 198960484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 199060484Sobrien#endif 199160484Sobrien return s->sy_frag; 199260484Sobrien} 199360484Sobrien 199460484Sobrien/* Mark a symbol as having been used. */ 199560484Sobrien 199660484Sobrienvoid 199760484Sobriensymbol_mark_used (s) 199860484Sobrien symbolS *s; 199960484Sobrien{ 200060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 200160484Sobrien return; 200260484Sobrien s->sy_used = 1; 200360484Sobrien} 200460484Sobrien 200560484Sobrien/* Clear the mark of whether a symbol has been used. */ 200660484Sobrien 200760484Sobrienvoid 200860484Sobriensymbol_clear_used (s) 200960484Sobrien symbolS *s; 201060484Sobrien{ 201160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 201260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 201360484Sobrien s->sy_used = 0; 201460484Sobrien} 201560484Sobrien 201660484Sobrien/* Return whether a symbol has been used. */ 201760484Sobrien 201860484Sobrienint 201960484Sobriensymbol_used_p (s) 202060484Sobrien symbolS *s; 202160484Sobrien{ 202260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202360484Sobrien return 1; 202460484Sobrien return s->sy_used; 202560484Sobrien} 202660484Sobrien 202760484Sobrien/* Mark a symbol as having been used in a reloc. */ 202860484Sobrien 202960484Sobrienvoid 203060484Sobriensymbol_mark_used_in_reloc (s) 203160484Sobrien symbolS *s; 203260484Sobrien{ 203360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 203460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 203560484Sobrien s->sy_used_in_reloc = 1; 203660484Sobrien} 203760484Sobrien 203860484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 203960484Sobrien 204060484Sobrienvoid 204160484Sobriensymbol_clear_used_in_reloc (s) 204260484Sobrien symbolS *s; 204360484Sobrien{ 204460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 204560484Sobrien return; 204660484Sobrien s->sy_used_in_reloc = 0; 204760484Sobrien} 204860484Sobrien 204960484Sobrien/* Return whether a symbol has been used in a reloc. */ 205060484Sobrien 205160484Sobrienint 205260484Sobriensymbol_used_in_reloc_p (s) 205360484Sobrien symbolS *s; 205460484Sobrien{ 205560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 205660484Sobrien return 0; 205760484Sobrien return s->sy_used_in_reloc; 205860484Sobrien} 205960484Sobrien 206060484Sobrien/* Mark a symbol as an MRI common symbol. */ 206160484Sobrien 206260484Sobrienvoid 206360484Sobriensymbol_mark_mri_common (s) 206460484Sobrien symbolS *s; 206560484Sobrien{ 206660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 206760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 206860484Sobrien s->sy_mri_common = 1; 206960484Sobrien} 207060484Sobrien 207160484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 207260484Sobrien 207360484Sobrienvoid 207460484Sobriensymbol_clear_mri_common (s) 207560484Sobrien symbolS *s; 207660484Sobrien{ 207760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207860484Sobrien return; 207960484Sobrien s->sy_mri_common = 0; 208060484Sobrien} 208160484Sobrien 208260484Sobrien/* Return whether a symbol is an MRI common symbol. */ 208360484Sobrien 208460484Sobrienint 208560484Sobriensymbol_mri_common_p (s) 208660484Sobrien symbolS *s; 208760484Sobrien{ 208860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 208960484Sobrien return 0; 209060484Sobrien return s->sy_mri_common; 209160484Sobrien} 209260484Sobrien 209360484Sobrien/* Mark a symbol as having been written. */ 209460484Sobrien 209560484Sobrienvoid 209660484Sobriensymbol_mark_written (s) 209760484Sobrien symbolS *s; 209860484Sobrien{ 209960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 210060484Sobrien return; 210160484Sobrien s->written = 1; 210260484Sobrien} 210360484Sobrien 210460484Sobrien/* Clear the mark of whether a symbol has been written. */ 210560484Sobrien 210660484Sobrienvoid 210760484Sobriensymbol_clear_written (s) 210860484Sobrien symbolS *s; 210960484Sobrien{ 211060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 211160484Sobrien return; 211260484Sobrien s->written = 0; 211360484Sobrien} 211460484Sobrien 211560484Sobrien/* Return whether a symbol has been written. */ 211660484Sobrien 211760484Sobrienint 211860484Sobriensymbol_written_p (s) 211960484Sobrien symbolS *s; 212060484Sobrien{ 212160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212260484Sobrien return 0; 212360484Sobrien return s->written; 212460484Sobrien} 212560484Sobrien 212660484Sobrien/* Mark a symbol has having been resolved. */ 212760484Sobrien 212860484Sobrienvoid 212960484Sobriensymbol_mark_resolved (s) 213060484Sobrien symbolS *s; 213160484Sobrien{ 213260484Sobrien#ifdef BFD_ASSEMBLER 213360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213460484Sobrien { 213560484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 213660484Sobrien return; 213760484Sobrien } 213860484Sobrien#endif 213960484Sobrien s->sy_resolved = 1; 214060484Sobrien} 214160484Sobrien 214260484Sobrien/* Return whether a symbol has been resolved. */ 214360484Sobrien 214460484Sobrienint 214560484Sobriensymbol_resolved_p (s) 214660484Sobrien symbolS *s; 214760484Sobrien{ 214860484Sobrien#ifdef BFD_ASSEMBLER 214960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 215060484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 215160484Sobrien#endif 215260484Sobrien return s->sy_resolved; 215360484Sobrien} 215460484Sobrien 215560484Sobrien/* Return whether a symbol is a section symbol. */ 215660484Sobrien 215760484Sobrienint 215860484Sobriensymbol_section_p (s) 215960484Sobrien symbolS *s ATTRIBUTE_UNUSED; 216060484Sobrien{ 216160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 216260484Sobrien return 0; 216360484Sobrien#ifdef BFD_ASSEMBLER 216460484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 216560484Sobrien#else 216677298Sobrien /* FIXME. */ 216760484Sobrien return 0; 216860484Sobrien#endif 216960484Sobrien} 217060484Sobrien 217160484Sobrien/* Return whether a symbol is equated to another symbol. */ 217260484Sobrien 217360484Sobrienint 217460484Sobriensymbol_equated_p (s) 217560484Sobrien symbolS *s; 217660484Sobrien{ 217760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217860484Sobrien return 0; 217960484Sobrien return s->sy_value.X_op == O_symbol; 218060484Sobrien} 218160484Sobrien 218289857Sobrien/* Return whether a symbol is equated to another symbol, and should be 218389857Sobrien treated specially when writing out relocs. */ 218489857Sobrien 218589857Sobrienint 218689857Sobriensymbol_equated_reloc_p (s) 218789857Sobrien symbolS *s; 218889857Sobrien{ 218989857Sobrien if (LOCAL_SYMBOL_CHECK (s)) 219089857Sobrien return 0; 219189857Sobrien /* X_op_symbol, normally not used for O_symbol, is set by 219289857Sobrien resolve_symbol_value to flag expression syms that have been 219389857Sobrien equated. */ 219489857Sobrien return (s->sy_value.X_op == O_symbol 219589857Sobrien && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL) 219689857Sobrien || ! S_IS_DEFINED (s) 219789857Sobrien || S_IS_COMMON (s))); 219889857Sobrien} 219989857Sobrien 220060484Sobrien/* Return whether a symbol has a constant value. */ 220160484Sobrien 220260484Sobrienint 220360484Sobriensymbol_constant_p (s) 220460484Sobrien symbolS *s; 220560484Sobrien{ 220660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 220760484Sobrien return 1; 220860484Sobrien return s->sy_value.X_op == O_constant; 220960484Sobrien} 221060484Sobrien 221160484Sobrien#ifdef BFD_ASSEMBLER 221260484Sobrien 221360484Sobrien/* Return the BFD symbol for a symbol. */ 221460484Sobrien 221560484Sobrienasymbol * 221660484Sobriensymbol_get_bfdsym (s) 221760484Sobrien symbolS *s; 221860484Sobrien{ 221960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 222060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 222160484Sobrien return s->bsym; 222260484Sobrien} 222360484Sobrien 222460484Sobrien/* Set the BFD symbol for a symbol. */ 222560484Sobrien 222660484Sobrienvoid 222760484Sobriensymbol_set_bfdsym (s, bsym) 222860484Sobrien symbolS *s; 222960484Sobrien asymbol *bsym; 223060484Sobrien{ 223160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 223260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 223360484Sobrien s->bsym = bsym; 223460484Sobrien} 223560484Sobrien 223660484Sobrien#endif /* BFD_ASSEMBLER */ 223760484Sobrien 223860484Sobrien#ifdef OBJ_SYMFIELD_TYPE 223960484Sobrien 224060484Sobrien/* Get a pointer to the object format information for a symbol. */ 224160484Sobrien 224260484SobrienOBJ_SYMFIELD_TYPE * 224360484Sobriensymbol_get_obj (s) 224460484Sobrien symbolS *s; 224560484Sobrien{ 224660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 224760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 224860484Sobrien return &s->sy_obj; 224960484Sobrien} 225060484Sobrien 225160484Sobrien/* Set the object format information for a symbol. */ 225260484Sobrien 225360484Sobrienvoid 225460484Sobriensymbol_set_obj (s, o) 225560484Sobrien symbolS *s; 225660484Sobrien OBJ_SYMFIELD_TYPE *o; 225760484Sobrien{ 225860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 225960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 226060484Sobrien s->sy_obj = *o; 226160484Sobrien} 226260484Sobrien 226360484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 226460484Sobrien 226560484Sobrien#ifdef TC_SYMFIELD_TYPE 226660484Sobrien 226760484Sobrien/* Get a pointer to the processor information for a symbol. */ 226860484Sobrien 226960484SobrienTC_SYMFIELD_TYPE * 227060484Sobriensymbol_get_tc (s) 227160484Sobrien symbolS *s; 227260484Sobrien{ 227360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 227460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 227560484Sobrien return &s->sy_tc; 227660484Sobrien} 227760484Sobrien 227860484Sobrien/* Set the processor information for a symbol. */ 227960484Sobrien 228060484Sobrienvoid 228160484Sobriensymbol_set_tc (s, o) 228260484Sobrien symbolS *s; 228360484Sobrien TC_SYMFIELD_TYPE *o; 228460484Sobrien{ 228560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 228660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 228760484Sobrien s->sy_tc = *o; 228860484Sobrien} 228960484Sobrien 229060484Sobrien#endif /* TC_SYMFIELD_TYPE */ 229160484Sobrien 229260484Sobrienvoid 229333965Sjdpsymbol_begin () 229433965Sjdp{ 229533965Sjdp symbol_lastP = NULL; 229677298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 229733965Sjdp sy_hash = hash_new (); 229860484Sobrien#ifdef BFD_ASSEMBLER 229960484Sobrien local_hash = hash_new (); 230060484Sobrien#endif 230133965Sjdp 230233965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 230333965Sjdp#ifdef BFD_ASSEMBLER 230433965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 230533965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 230633965Sjdp#endif 230733965Sjdp#else 230877298Sobrien /* Can't initialise a union. Sigh. */ 230933965Sjdp S_SET_SEGMENT (&abs_symbol, absolute_section); 231033965Sjdp#endif 231133965Sjdp abs_symbol.sy_value.X_op = O_constant; 231233965Sjdp abs_symbol.sy_frag = &zero_address_frag; 231333965Sjdp 231433965Sjdp if (LOCAL_LABELS_FB) 231533965Sjdp fb_label_init (); 231633965Sjdp} 231733965Sjdp 231833965Sjdpint indent_level; 231933965Sjdp 232060484Sobrien/* Maximum indent level. 232160484Sobrien Available for modification inside a gdb session. */ 232260484Sobrienint max_indent_level = 8; 232360484Sobrien 232433965Sjdp#if 0 232533965Sjdp 232633965Sjdpstatic void 232733965Sjdpindent () 232833965Sjdp{ 232933965Sjdp printf ("%*s", indent_level * 4, ""); 233033965Sjdp} 233133965Sjdp 233233965Sjdp#endif 233333965Sjdp 233433965Sjdpvoid 233533965Sjdpprint_symbol_value_1 (file, sym) 233633965Sjdp FILE *file; 233733965Sjdp symbolS *sym; 233833965Sjdp{ 233933965Sjdp const char *name = S_GET_NAME (sym); 234033965Sjdp if (!name || !name[0]) 234133965Sjdp name = "(unnamed)"; 234233965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 234360484Sobrien 234460484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 234560484Sobrien { 234660484Sobrien#ifdef BFD_ASSEMBLER 234760484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 234860484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 234960484Sobrien && local_symbol_get_frag (locsym) != NULL) 235060484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 235160484Sobrien if (local_symbol_resolved_p (locsym)) 235260484Sobrien fprintf (file, " resolved"); 235360484Sobrien fprintf (file, " local"); 235460484Sobrien#endif 235560484Sobrien } 235660484Sobrien else 235760484Sobrien { 235860484Sobrien if (sym->sy_frag != &zero_address_frag) 235960484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 236060484Sobrien if (sym->written) 236160484Sobrien fprintf (file, " written"); 236260484Sobrien if (sym->sy_resolved) 236360484Sobrien fprintf (file, " resolved"); 236460484Sobrien else if (sym->sy_resolving) 236560484Sobrien fprintf (file, " resolving"); 236660484Sobrien if (sym->sy_used_in_reloc) 236760484Sobrien fprintf (file, " used-in-reloc"); 236860484Sobrien if (sym->sy_used) 236960484Sobrien fprintf (file, " used"); 237060484Sobrien if (S_IS_LOCAL (sym)) 237160484Sobrien fprintf (file, " local"); 237260484Sobrien if (S_IS_EXTERN (sym)) 237360484Sobrien fprintf (file, " extern"); 237460484Sobrien if (S_IS_DEBUG (sym)) 237560484Sobrien fprintf (file, " debug"); 237660484Sobrien if (S_IS_DEFINED (sym)) 237760484Sobrien fprintf (file, " defined"); 237860484Sobrien } 237933965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 238060484Sobrien if (symbol_resolved_p (sym)) 238133965Sjdp { 238233965Sjdp segT s = S_GET_SEGMENT (sym); 238333965Sjdp 238433965Sjdp if (s != undefined_section 238533965Sjdp && s != expr_section) 238633965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 238733965Sjdp } 238860484Sobrien else if (indent_level < max_indent_level 238960484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 239033965Sjdp { 239133965Sjdp indent_level++; 239233965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 239360484Sobrien#ifdef BFD_ASSEMBLER 239460484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 239560484Sobrien fprintf (file, "constant %lx", 239689857Sobrien (long) ((struct local_symbol *) sym)->lsy_value); 239760484Sobrien else 239860484Sobrien#endif 239960484Sobrien print_expr_1 (file, &sym->sy_value); 240033965Sjdp fprintf (file, ">"); 240133965Sjdp indent_level--; 240233965Sjdp } 240333965Sjdp fflush (file); 240433965Sjdp} 240533965Sjdp 240633965Sjdpvoid 240733965Sjdpprint_symbol_value (sym) 240833965Sjdp symbolS *sym; 240933965Sjdp{ 241033965Sjdp indent_level = 0; 241133965Sjdp print_symbol_value_1 (stderr, sym); 241233965Sjdp fprintf (stderr, "\n"); 241333965Sjdp} 241433965Sjdp 241560484Sobrienstatic void 241660484Sobrienprint_binary (file, name, exp) 241760484Sobrien FILE *file; 241877298Sobrien const char *name; 241960484Sobrien expressionS *exp; 242060484Sobrien{ 242160484Sobrien indent_level++; 242260484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 242360484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 242460484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 242560484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 242660484Sobrien fprintf (file, ">"); 242760484Sobrien indent_level--; 242860484Sobrien} 242960484Sobrien 243033965Sjdpvoid 243133965Sjdpprint_expr_1 (file, exp) 243233965Sjdp FILE *file; 243333965Sjdp expressionS *exp; 243433965Sjdp{ 243533965Sjdp fprintf (file, "expr %lx ", (long) exp); 243633965Sjdp switch (exp->X_op) 243733965Sjdp { 243833965Sjdp case O_illegal: 243933965Sjdp fprintf (file, "illegal"); 244033965Sjdp break; 244133965Sjdp case O_absent: 244233965Sjdp fprintf (file, "absent"); 244333965Sjdp break; 244433965Sjdp case O_constant: 244533965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 244633965Sjdp break; 244733965Sjdp case O_symbol: 244833965Sjdp indent_level++; 244933965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 245033965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 245133965Sjdp fprintf (file, ">"); 245233965Sjdp maybe_print_addnum: 245333965Sjdp if (exp->X_add_number) 245433965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 245533965Sjdp (long) exp->X_add_number); 245633965Sjdp indent_level--; 245733965Sjdp break; 245833965Sjdp case O_register: 245933965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 246033965Sjdp break; 246133965Sjdp case O_big: 246233965Sjdp fprintf (file, "big"); 246333965Sjdp break; 246433965Sjdp case O_uminus: 246533965Sjdp fprintf (file, "uminus -<"); 246633965Sjdp indent_level++; 246733965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 246833965Sjdp fprintf (file, ">"); 246933965Sjdp goto maybe_print_addnum; 247033965Sjdp case O_bit_not: 247133965Sjdp fprintf (file, "bit_not"); 247233965Sjdp break; 247333965Sjdp case O_multiply: 247460484Sobrien print_binary (file, "multiply", exp); 247533965Sjdp break; 247633965Sjdp case O_divide: 247760484Sobrien print_binary (file, "divide", exp); 247833965Sjdp break; 247933965Sjdp case O_modulus: 248060484Sobrien print_binary (file, "modulus", exp); 248133965Sjdp break; 248233965Sjdp case O_left_shift: 248360484Sobrien print_binary (file, "lshift", exp); 248433965Sjdp break; 248533965Sjdp case O_right_shift: 248660484Sobrien print_binary (file, "rshift", exp); 248733965Sjdp break; 248833965Sjdp case O_bit_inclusive_or: 248960484Sobrien print_binary (file, "bit_ior", exp); 249033965Sjdp break; 249133965Sjdp case O_bit_exclusive_or: 249260484Sobrien print_binary (file, "bit_xor", exp); 249333965Sjdp break; 249433965Sjdp case O_bit_and: 249560484Sobrien print_binary (file, "bit_and", exp); 249633965Sjdp break; 249733965Sjdp case O_eq: 249860484Sobrien print_binary (file, "eq", exp); 249933965Sjdp break; 250033965Sjdp case O_ne: 250160484Sobrien print_binary (file, "ne", exp); 250233965Sjdp break; 250333965Sjdp case O_lt: 250460484Sobrien print_binary (file, "lt", exp); 250533965Sjdp break; 250633965Sjdp case O_le: 250760484Sobrien print_binary (file, "le", exp); 250833965Sjdp break; 250933965Sjdp case O_ge: 251060484Sobrien print_binary (file, "ge", exp); 251133965Sjdp break; 251233965Sjdp case O_gt: 251360484Sobrien print_binary (file, "gt", exp); 251433965Sjdp break; 251533965Sjdp case O_logical_and: 251660484Sobrien print_binary (file, "logical_and", exp); 251733965Sjdp break; 251833965Sjdp case O_logical_or: 251960484Sobrien print_binary (file, "logical_or", exp); 252033965Sjdp break; 252133965Sjdp case O_add: 252233965Sjdp indent_level++; 252333965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 252433965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 252533965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 252633965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 252733965Sjdp fprintf (file, ">"); 252833965Sjdp goto maybe_print_addnum; 252933965Sjdp case O_subtract: 253033965Sjdp indent_level++; 253133965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 253233965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 253333965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 253433965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 253533965Sjdp fprintf (file, ">"); 253633965Sjdp goto maybe_print_addnum; 253733965Sjdp default: 253833965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 253933965Sjdp break; 254033965Sjdp } 254133965Sjdp fflush (stdout); 254233965Sjdp} 254333965Sjdp 254433965Sjdpvoid 254533965Sjdpprint_expr (exp) 254633965Sjdp expressionS *exp; 254733965Sjdp{ 254833965Sjdp print_expr_1 (stderr, exp); 254933965Sjdp fprintf (stderr, "\n"); 255033965Sjdp} 255133965Sjdp 255233965Sjdpvoid 255333965Sjdpsymbol_print_statistics (file) 255433965Sjdp FILE *file; 255533965Sjdp{ 255633965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 255760484Sobrien#ifdef BFD_ASSEMBLER 255860484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 255960484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 256060484Sobrien local_symbol_count, local_symbol_conversion_count); 256160484Sobrien#endif 256233965Sjdp} 2563