symbols.c revision 104834
133965Sjdp/* symbols.c -symbol table- 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3104834Sobrien 1999, 2000, 2001, 2002 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 442104834Sobrien sprintf (od_buf, "%d.%d.", 443104834Sobrien S_GET_OTHER (symbolP), 444104834Sobrien 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) 572104834Sobrien 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) 592104834Sobrien 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 * 602104834Sobriensymbol_find_exact (name) 603104834Sobrien const char *name; 604104834Sobrien{ 605104834Sobrien#ifdef BFD_ASSEMBLER 606104834Sobrien { 607104834Sobrien struct local_symbol *locsym; 608104834Sobrien 609104834Sobrien locsym = (struct local_symbol *) hash_find (local_hash, name); 610104834Sobrien if (locsym != NULL) 611104834Sobrien return (symbolS *) locsym; 612104834Sobrien } 613104834Sobrien#endif 614104834Sobrien 615104834Sobrien return ((symbolS *) hash_find (sy_hash, name)); 616104834Sobrien} 617104834Sobrien 618104834SobriensymbolS * 61933965Sjdpsymbol_find_base (name, strip_underscore) 620104834Sobrien const char *name; 62133965Sjdp int strip_underscore; 62233965Sjdp{ 62333965Sjdp if (strip_underscore && *name == '_') 62433965Sjdp name++; 62533965Sjdp 62633965Sjdp#ifdef tc_canonicalize_symbol_name 62733965Sjdp { 62833965Sjdp char *copy; 62960484Sobrien size_t len = strlen (name) + 1; 63033965Sjdp 63160484Sobrien copy = (char *) alloca (len); 63260484Sobrien memcpy (copy, name, len); 63333965Sjdp name = tc_canonicalize_symbol_name (copy); 63433965Sjdp } 63533965Sjdp#endif 63633965Sjdp 63733965Sjdp if (! symbols_case_sensitive) 63833965Sjdp { 63960484Sobrien char *copy; 64060484Sobrien const char *orig; 64160484Sobrien unsigned char c; 64233965Sjdp 64360484Sobrien orig = name; 64460484Sobrien name = copy = (char *) alloca (strlen (name) + 1); 64560484Sobrien 64660484Sobrien while ((c = *orig++) != '\0') 64760484Sobrien { 64889857Sobrien *copy++ = TOUPPER (c); 64960484Sobrien } 65060484Sobrien *copy = '\0'; 65133965Sjdp } 65233965Sjdp 653104834Sobrien return symbol_find_exact (name); 65433965Sjdp} 65533965Sjdp 65677298Sobrien/* Once upon a time, symbols were kept in a singly linked list. At 65777298Sobrien least coff needs to be able to rearrange them from time to time, for 65877298Sobrien which a doubly linked list is much more convenient. Loic did these 65977298Sobrien as macros which seemed dangerous to me so they're now functions. 66077298Sobrien xoxorich. */ 66133965Sjdp 66277298Sobrien/* Link symbol ADDME after symbol TARGET in the chain. */ 66377298Sobrien 66477298Sobrienvoid 66533965Sjdpsymbol_append (addme, target, rootPP, lastPP) 66633965Sjdp symbolS *addme; 66733965Sjdp symbolS *target; 66833965Sjdp symbolS **rootPP; 66933965Sjdp symbolS **lastPP; 67033965Sjdp{ 67160484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 67260484Sobrien abort (); 67360484Sobrien if (target != NULL && LOCAL_SYMBOL_CHECK (target)) 67460484Sobrien abort (); 67560484Sobrien 67633965Sjdp if (target == NULL) 67733965Sjdp { 67833965Sjdp know (*rootPP == NULL); 67933965Sjdp know (*lastPP == NULL); 68033965Sjdp addme->sy_next = NULL; 68133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 68233965Sjdp addme->sy_previous = NULL; 68333965Sjdp#endif 68433965Sjdp *rootPP = addme; 68533965Sjdp *lastPP = addme; 68633965Sjdp return; 68777298Sobrien } /* if the list is empty */ 68833965Sjdp 68933965Sjdp if (target->sy_next != NULL) 69033965Sjdp { 69133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 69233965Sjdp target->sy_next->sy_previous = addme; 69333965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 69433965Sjdp } 69533965Sjdp else 69633965Sjdp { 69733965Sjdp know (*lastPP == target); 69833965Sjdp *lastPP = addme; 69977298Sobrien } /* if we have a next */ 70033965Sjdp 70133965Sjdp addme->sy_next = target->sy_next; 70233965Sjdp target->sy_next = addme; 70333965Sjdp 70433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 70533965Sjdp addme->sy_previous = target; 70633965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 70733965Sjdp 70833965Sjdp debug_verify_symchain (symbol_rootP, symbol_lastP); 70933965Sjdp} 71033965Sjdp 71177298Sobrien/* Set the chain pointers of SYMBOL to null. */ 71277298Sobrien 71377298Sobrienvoid 71433965Sjdpsymbol_clear_list_pointers (symbolP) 71533965Sjdp symbolS *symbolP; 71633965Sjdp{ 71760484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 71860484Sobrien abort (); 71933965Sjdp symbolP->sy_next = NULL; 72033965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 72133965Sjdp symbolP->sy_previous = NULL; 72233965Sjdp#endif 72333965Sjdp} 72433965Sjdp 72533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 72677298Sobrien/* Remove SYMBOLP from the list. */ 72777298Sobrien 72877298Sobrienvoid 72933965Sjdpsymbol_remove (symbolP, rootPP, lastPP) 73033965Sjdp symbolS *symbolP; 73133965Sjdp symbolS **rootPP; 73233965Sjdp symbolS **lastPP; 73333965Sjdp{ 73460484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 73560484Sobrien abort (); 73660484Sobrien 73733965Sjdp if (symbolP == *rootPP) 73833965Sjdp { 73933965Sjdp *rootPP = symbolP->sy_next; 74077298Sobrien } /* if it was the root */ 74133965Sjdp 74233965Sjdp if (symbolP == *lastPP) 74333965Sjdp { 74433965Sjdp *lastPP = symbolP->sy_previous; 74577298Sobrien } /* if it was the tail */ 74633965Sjdp 74733965Sjdp if (symbolP->sy_next != NULL) 74833965Sjdp { 74933965Sjdp symbolP->sy_next->sy_previous = symbolP->sy_previous; 75077298Sobrien } /* if not last */ 75133965Sjdp 75233965Sjdp if (symbolP->sy_previous != NULL) 75333965Sjdp { 75433965Sjdp symbolP->sy_previous->sy_next = symbolP->sy_next; 75577298Sobrien } /* if not first */ 75633965Sjdp 75733965Sjdp debug_verify_symchain (*rootPP, *lastPP); 75833965Sjdp} 75933965Sjdp 76077298Sobrien/* Link symbol ADDME before symbol TARGET in the chain. */ 76177298Sobrien 76277298Sobrienvoid 76333965Sjdpsymbol_insert (addme, target, rootPP, lastPP) 76433965Sjdp symbolS *addme; 76533965Sjdp symbolS *target; 76633965Sjdp symbolS **rootPP; 76760484Sobrien symbolS **lastPP ATTRIBUTE_UNUSED; 76833965Sjdp{ 76960484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 77060484Sobrien abort (); 77160484Sobrien if (LOCAL_SYMBOL_CHECK (target)) 77260484Sobrien abort (); 77360484Sobrien 77433965Sjdp if (target->sy_previous != NULL) 77533965Sjdp { 77633965Sjdp target->sy_previous->sy_next = addme; 77733965Sjdp } 77833965Sjdp else 77933965Sjdp { 78033965Sjdp know (*rootPP == target); 78133965Sjdp *rootPP = addme; 78277298Sobrien } /* if not first */ 78333965Sjdp 78433965Sjdp addme->sy_previous = target->sy_previous; 78533965Sjdp target->sy_previous = addme; 78633965Sjdp addme->sy_next = target; 78733965Sjdp 78833965Sjdp debug_verify_symchain (*rootPP, *lastPP); 78933965Sjdp} 79033965Sjdp 79133965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 79233965Sjdp 79377298Sobrienvoid 79433965Sjdpverify_symbol_chain (rootP, lastP) 79533965Sjdp symbolS *rootP; 79633965Sjdp symbolS *lastP; 79733965Sjdp{ 79833965Sjdp symbolS *symbolP = rootP; 79933965Sjdp 80033965Sjdp if (symbolP == NULL) 80133965Sjdp return; 80233965Sjdp 80333965Sjdp for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) 80433965Sjdp { 80560484Sobrien#ifdef BFD_ASSEMBLER 80660484Sobrien assert (symbolP->bsym != NULL); 80760484Sobrien#endif 80833965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 80933965Sjdp assert (symbolP->sy_next->sy_previous == symbolP); 81033965Sjdp#else 81133965Sjdp /* Walk the list anyways, to make sure pointers are still good. */ 81233965Sjdp ; 81333965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 81433965Sjdp } 81533965Sjdp 81633965Sjdp assert (lastP == symbolP); 81733965Sjdp} 81833965Sjdp 81933965Sjdpvoid 82033965Sjdpverify_symbol_chain_2 (sym) 82133965Sjdp symbolS *sym; 82233965Sjdp{ 82333965Sjdp symbolS *p = sym, *n = sym; 82433965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 82533965Sjdp while (symbol_previous (p)) 82633965Sjdp p = symbol_previous (p); 82733965Sjdp#endif 82833965Sjdp while (symbol_next (n)) 82933965Sjdp n = symbol_next (n); 83033965Sjdp verify_symbol_chain (p, n); 83133965Sjdp} 83233965Sjdp 83333965Sjdp/* Resolve the value of a symbol. This is called during the final 83433965Sjdp pass over the symbol table to resolve any symbols with complex 83533965Sjdp values. */ 83633965Sjdp 83738889SjdpvalueT 83889857Sobrienresolve_symbol_value (symp) 83933965Sjdp symbolS *symp; 84033965Sjdp{ 84133965Sjdp int resolved; 842104834Sobrien valueT final_val = 0; 84338889Sjdp segT final_seg; 84433965Sjdp 84560484Sobrien#ifdef BFD_ASSEMBLER 84660484Sobrien if (LOCAL_SYMBOL_CHECK (symp)) 84760484Sobrien { 84860484Sobrien struct local_symbol *locsym = (struct local_symbol *) symp; 84960484Sobrien 85089857Sobrien final_val = locsym->lsy_value; 85160484Sobrien if (local_symbol_resolved_p (locsym)) 85289857Sobrien return final_val; 85360484Sobrien 85489857Sobrien final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE; 85560484Sobrien 85689857Sobrien if (finalize_syms) 85760484Sobrien { 85889857Sobrien locsym->lsy_value = final_val; 85960484Sobrien local_symbol_mark_resolved (locsym); 86060484Sobrien } 86160484Sobrien 86260484Sobrien return final_val; 86360484Sobrien } 86460484Sobrien#endif 86560484Sobrien 86633965Sjdp if (symp->sy_resolved) 86738889Sjdp { 86838889Sjdp if (symp->sy_value.X_op == O_constant) 86938889Sjdp return (valueT) symp->sy_value.X_add_number; 87038889Sjdp else 87138889Sjdp return 0; 87238889Sjdp } 87333965Sjdp 87433965Sjdp resolved = 0; 87538889Sjdp final_seg = S_GET_SEGMENT (symp); 87633965Sjdp 87733965Sjdp if (symp->sy_resolving) 87833965Sjdp { 87989857Sobrien if (finalize_syms) 88089857Sobrien as_bad (_("symbol definition loop encountered at `%s'"), 88177298Sobrien S_GET_NAME (symp)); 88238889Sjdp final_val = 0; 88333965Sjdp resolved = 1; 88433965Sjdp } 88533965Sjdp else 88633965Sjdp { 88738889Sjdp symbolS *add_symbol, *op_symbol; 88838889Sjdp offsetT left, right; 88933965Sjdp segT seg_left, seg_right; 89038889Sjdp operatorT op; 89133965Sjdp 89233965Sjdp symp->sy_resolving = 1; 89333965Sjdp 89438889Sjdp /* Help out with CSE. */ 89538889Sjdp add_symbol = symp->sy_value.X_add_symbol; 89638889Sjdp op_symbol = symp->sy_value.X_op_symbol; 89738889Sjdp final_val = symp->sy_value.X_add_number; 89838889Sjdp op = symp->sy_value.X_op; 89938889Sjdp 90038889Sjdp switch (op) 90133965Sjdp { 90238889Sjdp default: 90338889Sjdp BAD_CASE (op); 90438889Sjdp break; 90533965Sjdp 90633965Sjdp case O_absent: 90738889Sjdp final_val = 0; 90833965Sjdp /* Fall through. */ 90938889Sjdp 91033965Sjdp case O_constant: 91160484Sobrien final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; 91238889Sjdp if (final_seg == expr_section) 91338889Sjdp final_seg = absolute_section; 91433965Sjdp resolved = 1; 91533965Sjdp break; 91633965Sjdp 91733965Sjdp case O_symbol: 91838889Sjdp case O_symbol_rva: 91989857Sobrien left = resolve_symbol_value (add_symbol); 92089857Sobrien seg_left = S_GET_SEGMENT (add_symbol); 92189857Sobrien if (finalize_syms) 92289857Sobrien symp->sy_value.X_op_symbol = NULL; 92389857Sobrien 92438889Sjdp do_symbol: 92533965Sjdp if (symp->sy_mri_common) 92633965Sjdp { 92733965Sjdp /* This is a symbol inside an MRI common section. The 92889857Sobrien relocation routines are going to handle it specially. 92989857Sobrien Don't change the value. */ 93060484Sobrien resolved = symbol_resolved_p (add_symbol); 93133965Sjdp break; 93233965Sjdp } 93333965Sjdp 93489857Sobrien if (finalize_syms && final_val == 0) 93560484Sobrien { 93660484Sobrien if (LOCAL_SYMBOL_CHECK (add_symbol)) 93760484Sobrien add_symbol = local_symbol_convert ((struct local_symbol *) 93860484Sobrien add_symbol); 93960484Sobrien copy_symbol_attributes (symp, add_symbol); 94060484Sobrien } 94133965Sjdp 94289857Sobrien /* If we have equated this symbol to an undefined or common 94389857Sobrien symbol, keep X_op set to O_symbol, and don't change 94489857Sobrien X_add_number. This permits the routine which writes out 94589857Sobrien relocation to detect this case, and convert the 94689857Sobrien relocation to be against the symbol to which this symbol 94789857Sobrien is equated. */ 94838889Sjdp if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol)) 94933965Sjdp { 95089857Sobrien if (finalize_syms) 95138889Sjdp { 95238889Sjdp symp->sy_value.X_op = O_symbol; 95360484Sobrien symp->sy_value.X_add_symbol = add_symbol; 95438889Sjdp symp->sy_value.X_add_number = final_val; 95589857Sobrien /* Use X_op_symbol as a flag. */ 95689857Sobrien symp->sy_value.X_op_symbol = add_symbol; 95789857Sobrien final_seg = seg_left; 95838889Sjdp } 95938889Sjdp final_val = 0; 96060484Sobrien resolved = symbol_resolved_p (add_symbol); 96189857Sobrien symp->sy_resolving = 0; 96238889Sjdp goto exit_dont_set_value; 96333965Sjdp } 96489857Sobrien else if (finalize_syms && final_seg == expr_section 96589857Sobrien && seg_left != expr_section) 96689857Sobrien { 96789857Sobrien /* If the symbol is an expression symbol, do similarly 96889857Sobrien as for undefined and common syms above. Handles 96989857Sobrien "sym +/- expr" where "expr" cannot be evaluated 97089857Sobrien immediately, and we want relocations to be against 97189857Sobrien "sym", eg. because it is weak. */ 97289857Sobrien symp->sy_value.X_op = O_symbol; 97389857Sobrien symp->sy_value.X_add_symbol = add_symbol; 97489857Sobrien symp->sy_value.X_add_number = final_val; 97589857Sobrien symp->sy_value.X_op_symbol = add_symbol; 97689857Sobrien final_seg = seg_left; 97789857Sobrien final_val += symp->sy_frag->fr_address + left; 97889857Sobrien resolved = symbol_resolved_p (add_symbol); 97989857Sobrien symp->sy_resolving = 0; 98089857Sobrien goto exit_dont_set_value; 98189857Sobrien } 98233965Sjdp else 98333965Sjdp { 98438889Sjdp final_val += symp->sy_frag->fr_address + left; 98538889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 98689857Sobrien final_seg = seg_left; 98733965Sjdp } 98833965Sjdp 98960484Sobrien resolved = symbol_resolved_p (add_symbol); 99033965Sjdp break; 99133965Sjdp 99233965Sjdp case O_uminus: 99333965Sjdp case O_bit_not: 99433965Sjdp case O_logical_not: 99589857Sobrien left = resolve_symbol_value (add_symbol); 99699461Sobrien seg_left = S_GET_SEGMENT (add_symbol); 99738889Sjdp 99838889Sjdp if (op == O_uminus) 99938889Sjdp left = -left; 100038889Sjdp else if (op == O_logical_not) 100138889Sjdp left = !left; 100233965Sjdp else 100338889Sjdp left = ~left; 100438889Sjdp 100538889Sjdp final_val += left + symp->sy_frag->fr_address; 100638889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 100799461Sobrien final_seg = seg_left; 100838889Sjdp 100960484Sobrien resolved = symbol_resolved_p (add_symbol); 101033965Sjdp break; 101133965Sjdp 101233965Sjdp case O_multiply: 101333965Sjdp case O_divide: 101433965Sjdp case O_modulus: 101533965Sjdp case O_left_shift: 101633965Sjdp case O_right_shift: 101733965Sjdp case O_bit_inclusive_or: 101833965Sjdp case O_bit_or_not: 101933965Sjdp case O_bit_exclusive_or: 102033965Sjdp case O_bit_and: 102133965Sjdp case O_add: 102233965Sjdp case O_subtract: 102333965Sjdp case O_eq: 102433965Sjdp case O_ne: 102533965Sjdp case O_lt: 102633965Sjdp case O_le: 102733965Sjdp case O_ge: 102833965Sjdp case O_gt: 102933965Sjdp case O_logical_and: 103033965Sjdp case O_logical_or: 103189857Sobrien left = resolve_symbol_value (add_symbol); 103289857Sobrien right = resolve_symbol_value (op_symbol); 103338889Sjdp seg_left = S_GET_SEGMENT (add_symbol); 103438889Sjdp seg_right = S_GET_SEGMENT (op_symbol); 103533965Sjdp 103638889Sjdp /* Simplify addition or subtraction of a constant by folding the 103738889Sjdp constant into X_add_number. */ 103889857Sobrien if (op == O_add) 103938889Sjdp { 104038889Sjdp if (seg_right == absolute_section) 104138889Sjdp { 104289857Sobrien final_val += right; 104338889Sjdp goto do_symbol; 104438889Sjdp } 104589857Sobrien else if (seg_left == absolute_section) 104638889Sjdp { 104738889Sjdp final_val += left; 104838889Sjdp add_symbol = op_symbol; 104938889Sjdp left = right; 105089857Sobrien seg_left = seg_right; 105138889Sjdp goto do_symbol; 105238889Sjdp } 105338889Sjdp } 105489857Sobrien else if (op == O_subtract) 105589857Sobrien { 105689857Sobrien if (seg_right == absolute_section) 105789857Sobrien { 105889857Sobrien final_val -= right; 105989857Sobrien goto do_symbol; 106089857Sobrien } 106189857Sobrien } 106238889Sjdp 106389857Sobrien /* Equality and non-equality tests are permitted on anything. 106489857Sobrien Subtraction, and other comparison operators are permitted if 106589857Sobrien both operands are in the same section. Otherwise, both 106689857Sobrien operands must be absolute. We already handled the case of 106789857Sobrien addition or subtraction of a constant above. This will 106889857Sobrien probably need to be changed for an object file format which 106989857Sobrien supports arbitrary expressions, such as IEEE-695. 107089857Sobrien 107189857Sobrien Don't emit messages unless we're finalizing the symbol value, 107238889Sjdp otherwise we may get the same message multiple times. */ 107399461Sobrien if ((op == O_eq || op == O_ne) 107499461Sobrien || ((op == O_subtract 107599461Sobrien || op == O_lt || op == O_le || op == O_ge || op == O_gt) 107699461Sobrien && seg_left == seg_right 107799461Sobrien && (seg_left != undefined_section 107899461Sobrien || add_symbol == op_symbol)) 107999461Sobrien || (seg_left == absolute_section 108099461Sobrien && seg_right == absolute_section)) 108133965Sjdp { 108299461Sobrien if (final_seg == expr_section || final_seg == undefined_section) 108399461Sobrien final_seg = absolute_section; 108499461Sobrien } 108599461Sobrien else if (finalize_syms) 108699461Sobrien { 108733965Sjdp char *file; 108833965Sjdp unsigned int line; 108933965Sjdp 109033965Sjdp if (expr_symbol_where (symp, &file, &line)) 109133965Sjdp { 109233965Sjdp if (seg_left == undefined_section) 109333965Sjdp as_bad_where (file, line, 109489857Sobrien _("undefined symbol `%s' in operation"), 109533965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol)); 109633965Sjdp if (seg_right == undefined_section) 109733965Sjdp as_bad_where (file, line, 109889857Sobrien _("undefined symbol `%s' in operation"), 109933965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol)); 110033965Sjdp if (seg_left != undefined_section 110133965Sjdp && seg_right != undefined_section) 110277298Sobrien as_bad_where (file, line, 110377298Sobrien _("invalid section for operation")); 110433965Sjdp } 110533965Sjdp else 110633965Sjdp { 110733965Sjdp if (seg_left == undefined_section) 110889857Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 110933965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol), 111033965Sjdp S_GET_NAME (symp)); 111133965Sjdp if (seg_right == undefined_section) 111289857Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 111333965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol), 111433965Sjdp S_GET_NAME (symp)); 111533965Sjdp if (seg_left != undefined_section 111633965Sjdp && seg_right != undefined_section) 111789857Sobrien as_bad (_("invalid section for operation setting `%s'"), 111833965Sjdp S_GET_NAME (symp)); 111933965Sjdp } 112099461Sobrien /* Prevent the error propagating. */ 112199461Sobrien if (final_seg == expr_section || final_seg == undefined_section) 112299461Sobrien final_seg = absolute_section; 112333965Sjdp } 112433965Sjdp 112538889Sjdp /* Check for division by zero. */ 112638889Sjdp if ((op == O_divide || op == O_modulus) && right == 0) 112738889Sjdp { 112838889Sjdp /* If seg_right is not absolute_section, then we've 112989857Sobrien already issued a warning about using a bad symbol. */ 113089857Sobrien if (seg_right == absolute_section && finalize_syms) 113138889Sjdp { 113238889Sjdp char *file; 113338889Sjdp unsigned int line; 113438889Sjdp 113538889Sjdp if (expr_symbol_where (symp, &file, &line)) 113660484Sobrien as_bad_where (file, line, _("division by zero")); 113738889Sjdp else 113889857Sobrien as_bad (_("division by zero when setting `%s'"), 113938889Sjdp S_GET_NAME (symp)); 114038889Sjdp } 114138889Sjdp 114238889Sjdp right = 1; 114338889Sjdp } 114438889Sjdp 114533965Sjdp switch (symp->sy_value.X_op) 114633965Sjdp { 114738889Sjdp case O_multiply: left *= right; break; 114838889Sjdp case O_divide: left /= right; break; 114938889Sjdp case O_modulus: left %= right; break; 115038889Sjdp case O_left_shift: left <<= right; break; 115138889Sjdp case O_right_shift: left >>= right; break; 115238889Sjdp case O_bit_inclusive_or: left |= right; break; 115338889Sjdp case O_bit_or_not: left |= ~right; break; 115438889Sjdp case O_bit_exclusive_or: left ^= right; break; 115538889Sjdp case O_bit_and: left &= right; break; 115638889Sjdp case O_add: left += right; break; 115738889Sjdp case O_subtract: left -= right; break; 115889857Sobrien case O_eq: 115989857Sobrien case O_ne: 116089857Sobrien left = (left == right && seg_left == seg_right 116189857Sobrien && (seg_left != undefined_section 116289857Sobrien || add_symbol == op_symbol) 116389857Sobrien ? ~ (offsetT) 0 : 0); 116489857Sobrien if (symp->sy_value.X_op == O_ne) 116589857Sobrien left = ~left; 116689857Sobrien break; 116738889Sjdp case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; 116838889Sjdp case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; 116938889Sjdp case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; 117038889Sjdp case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; 117138889Sjdp case O_logical_and: left = left && right; break; 117238889Sjdp case O_logical_or: left = left || right; break; 117338889Sjdp default: abort (); 117433965Sjdp } 117538889Sjdp 117638889Sjdp final_val += symp->sy_frag->fr_address + left; 117738889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 117899461Sobrien { 117999461Sobrien if (seg_left == undefined_section 118099461Sobrien || seg_right == undefined_section) 118199461Sobrien final_seg = undefined_section; 118299461Sobrien else if (seg_left == absolute_section) 118399461Sobrien final_seg = seg_right; 118499461Sobrien else 118599461Sobrien final_seg = seg_left; 118699461Sobrien } 118760484Sobrien resolved = (symbol_resolved_p (add_symbol) 118860484Sobrien && symbol_resolved_p (op_symbol)); 118977298Sobrien break; 119033965Sjdp 119133965Sjdp case O_register: 119233965Sjdp case O_big: 119333965Sjdp case O_illegal: 119433965Sjdp /* Give an error (below) if not in expr_section. We don't 119533965Sjdp want to worry about expr_section symbols, because they 119633965Sjdp are fictional (they are created as part of expression 119733965Sjdp resolution), and any problems may not actually mean 119833965Sjdp anything. */ 119933965Sjdp break; 120033965Sjdp } 120138889Sjdp 120238889Sjdp symp->sy_resolving = 0; 120333965Sjdp } 120433965Sjdp 120589857Sobrien if (finalize_syms) 120689857Sobrien S_SET_VALUE (symp, final_val); 120738889Sjdp 120889857Sobrienexit_dont_set_value: 120989857Sobrien /* Always set the segment, even if not finalizing the value. 121089857Sobrien The segment is used to determine whether a symbol is defined. */ 121138889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER) 121289857Sobrien /* The old a.out backend does not handle S_SET_SEGMENT correctly 121389857Sobrien for a stab symbol, so we use this bad hack. */ 121489857Sobrien if (final_seg != S_GET_SEGMENT (symp)) 121538889Sjdp#endif 121689857Sobrien S_SET_SEGMENT (symp, final_seg); 121738889Sjdp 121833965Sjdp /* Don't worry if we can't resolve an expr_section symbol. */ 121989857Sobrien if (finalize_syms) 122033965Sjdp { 122138889Sjdp if (resolved) 122238889Sjdp symp->sy_resolved = 1; 122338889Sjdp else if (S_GET_SEGMENT (symp) != expr_section) 122438889Sjdp { 122589857Sobrien as_bad (_("can't resolve value for symbol `%s'"), 122677298Sobrien S_GET_NAME (symp)); 122738889Sjdp symp->sy_resolved = 1; 122838889Sjdp } 122933965Sjdp } 123038889Sjdp 123138889Sjdp return final_val; 123233965Sjdp} 123333965Sjdp 123460484Sobrien#ifdef BFD_ASSEMBLER 123560484Sobrien 123660484Sobrienstatic void resolve_local_symbol PARAMS ((const char *, PTR)); 123760484Sobrien 123860484Sobrien/* A static function passed to hash_traverse. */ 123960484Sobrien 124060484Sobrienstatic void 124160484Sobrienresolve_local_symbol (key, value) 124260484Sobrien const char *key ATTRIBUTE_UNUSED; 124360484Sobrien PTR value; 124460484Sobrien{ 124560484Sobrien if (value != NULL) 124689857Sobrien resolve_symbol_value (value); 124760484Sobrien} 124860484Sobrien 124960484Sobrien#endif 125060484Sobrien 125160484Sobrien/* Resolve all local symbols. */ 125260484Sobrien 125360484Sobrienvoid 125460484Sobrienresolve_local_symbol_values () 125560484Sobrien{ 125660484Sobrien#ifdef BFD_ASSEMBLER 125760484Sobrien hash_traverse (local_hash, resolve_local_symbol); 125860484Sobrien#endif 125960484Sobrien} 126060484Sobrien 126133965Sjdp/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". 126233965Sjdp They are *really* local. That is, they go out of scope whenever we see a 126333965Sjdp label that isn't local. Also, like fb labels, there can be multiple 126433965Sjdp instances of a dollar label. Therefor, we name encode each instance with 126533965Sjdp the instance number, keep a list of defined symbols separate from the real 126633965Sjdp symbol table, and we treat these buggers as a sparse array. */ 126733965Sjdp 126833965Sjdpstatic long *dollar_labels; 126933965Sjdpstatic long *dollar_label_instances; 127033965Sjdpstatic char *dollar_label_defines; 127138889Sjdpstatic unsigned long dollar_label_count; 127233965Sjdpstatic unsigned long dollar_label_max; 127333965Sjdp 127477298Sobrienint 127533965Sjdpdollar_label_defined (label) 127633965Sjdp long label; 127733965Sjdp{ 127833965Sjdp long *i; 127933965Sjdp 128033965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 128133965Sjdp 128233965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 128333965Sjdp if (*i == label) 128433965Sjdp return dollar_label_defines[i - dollar_labels]; 128533965Sjdp 128677298Sobrien /* If we get here, label isn't defined. */ 128733965Sjdp return 0; 128877298Sobrien} 128933965Sjdp 129033965Sjdpstatic long 129133965Sjdpdollar_label_instance (label) 129233965Sjdp long label; 129333965Sjdp{ 129433965Sjdp long *i; 129533965Sjdp 129633965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 129733965Sjdp 129833965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 129933965Sjdp if (*i == label) 130033965Sjdp return (dollar_label_instances[i - dollar_labels]); 130133965Sjdp 130277298Sobrien /* If we get here, we haven't seen the label before. 130377298Sobrien Therefore its instance count is zero. */ 130433965Sjdp return 0; 130533965Sjdp} 130633965Sjdp 130777298Sobrienvoid 130833965Sjdpdollar_label_clear () 130933965Sjdp{ 131033965Sjdp memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count); 131133965Sjdp} 131233965Sjdp 131333965Sjdp#define DOLLAR_LABEL_BUMP_BY 10 131433965Sjdp 131577298Sobrienvoid 131633965Sjdpdefine_dollar_label (label) 131733965Sjdp long label; 131833965Sjdp{ 131933965Sjdp long *i; 132033965Sjdp 132133965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 132233965Sjdp if (*i == label) 132333965Sjdp { 132433965Sjdp ++dollar_label_instances[i - dollar_labels]; 132533965Sjdp dollar_label_defines[i - dollar_labels] = 1; 132633965Sjdp return; 132733965Sjdp } 132833965Sjdp 132977298Sobrien /* If we get to here, we don't have label listed yet. */ 133033965Sjdp 133133965Sjdp if (dollar_labels == NULL) 133233965Sjdp { 133333965Sjdp dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 133433965Sjdp dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 133533965Sjdp dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY); 133633965Sjdp dollar_label_max = DOLLAR_LABEL_BUMP_BY; 133733965Sjdp dollar_label_count = 0; 133833965Sjdp } 133933965Sjdp else if (dollar_label_count == dollar_label_max) 134033965Sjdp { 134133965Sjdp dollar_label_max += DOLLAR_LABEL_BUMP_BY; 134233965Sjdp dollar_labels = (long *) xrealloc ((char *) dollar_labels, 134333965Sjdp dollar_label_max * sizeof (long)); 134433965Sjdp dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances, 134533965Sjdp dollar_label_max * sizeof (long)); 134633965Sjdp dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max); 134777298Sobrien } /* if we needed to grow */ 134833965Sjdp 134933965Sjdp dollar_labels[dollar_label_count] = label; 135033965Sjdp dollar_label_instances[dollar_label_count] = 1; 135133965Sjdp dollar_label_defines[dollar_label_count] = 1; 135233965Sjdp ++dollar_label_count; 135333965Sjdp} 135433965Sjdp 135577298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 135633965Sjdp 135777298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Am" 135877298Sobrien where n is the label number and m is the instance number. "L" makes 135977298Sobrien it a label discarded unless debugging and "^A"('\1') ensures no 136077298Sobrien ordinary symbol SHOULD get the same name as a local label 136177298Sobrien symbol. The first "4:" is "L4^A1" - the m numbers begin at 1. 136277298Sobrien 136377298Sobrien fb labels get the same treatment, except that ^B is used in place 136477298Sobrien of ^A. */ 136577298Sobrien 136677298Sobrienchar * /* Return local label name. */ 136733965Sjdpdollar_label_name (n, augend) 136877298Sobrien register long n; /* we just saw "n$:" : n a number. */ 136977298Sobrien register int augend; /* 0 for current instance, 1 for new instance. */ 137033965Sjdp{ 137133965Sjdp long i; 137277298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 137333965Sjdp static char symbol_name_build[24]; 137433965Sjdp register char *p; 137533965Sjdp register char *q; 137677298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 137733965Sjdp 137833965Sjdp know (n >= 0); 137933965Sjdp know (augend == 0 || augend == 1); 138033965Sjdp p = symbol_name_build; 138160484Sobrien#ifdef LOCAL_LABEL_PREFIX 138260484Sobrien *p++ = LOCAL_LABEL_PREFIX; 138360484Sobrien#endif 138433965Sjdp *p++ = 'L'; 138533965Sjdp 138677298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 138777298Sobrien /* Label number. */ 138833965Sjdp q = symbol_name_temporary; 138933965Sjdp for (*q++ = 0, i = n; i; ++q) 139033965Sjdp { 139133965Sjdp *q = i % 10 + '0'; 139233965Sjdp i /= 10; 139333965Sjdp } 139433965Sjdp while ((*p = *--q) != '\0') 139533965Sjdp ++p; 139633965Sjdp 139777298Sobrien *p++ = DOLLAR_LABEL_CHAR; /* ^A */ 139833965Sjdp 139977298Sobrien /* Instance number. */ 140033965Sjdp q = symbol_name_temporary; 140133965Sjdp for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q) 140233965Sjdp { 140333965Sjdp *q = i % 10 + '0'; 140433965Sjdp i /= 10; 140533965Sjdp } 140633965Sjdp while ((*p++ = *--q) != '\0');; 140733965Sjdp 140877298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 140933965Sjdp return symbol_name_build; 141033965Sjdp} 141133965Sjdp 141277298Sobrien/* Sombody else's idea of local labels. They are made by "n:" where n 141377298Sobrien is any decimal digit. Refer to them with 141477298Sobrien "nb" for previous (backward) n: 141577298Sobrien or "nf" for next (forward) n:. 141633965Sjdp 141777298Sobrien We do a little better and let n be any number, not just a single digit, but 141877298Sobrien since the other guy's assembler only does ten, we treat the first ten 141977298Sobrien specially. 142077298Sobrien 142177298Sobrien Like someone else's assembler, we have one set of local label counters for 142277298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 142377298Sobrien implies that one can refer to a label in another segment, and indeed some 142477298Sobrien crufty compilers have done just that. 142577298Sobrien 142677298Sobrien Since there could be a LOT of these things, treat them as a sparse 142777298Sobrien array. */ 142877298Sobrien 142933965Sjdp#define FB_LABEL_SPECIAL (10) 143033965Sjdp 143133965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 143233965Sjdpstatic long *fb_labels; 143333965Sjdpstatic long *fb_label_instances; 143433965Sjdpstatic long fb_label_count; 143533965Sjdpstatic long fb_label_max; 143633965Sjdp 143777298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 143833965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 143933965Sjdp 144077298Sobrienstatic void 144133965Sjdpfb_label_init () 144233965Sjdp{ 144333965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 144477298Sobrien} 144533965Sjdp 144677298Sobrien/* Add one to the instance number of this fb label. */ 144777298Sobrien 144877298Sobrienvoid 144933965Sjdpfb_label_instance_inc (label) 145033965Sjdp long label; 145133965Sjdp{ 145233965Sjdp long *i; 145333965Sjdp 145433965Sjdp if (label < FB_LABEL_SPECIAL) 145533965Sjdp { 145633965Sjdp ++fb_low_counter[label]; 145733965Sjdp return; 145833965Sjdp } 145933965Sjdp 146033965Sjdp if (fb_labels != NULL) 146133965Sjdp { 146233965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 146333965Sjdp i < fb_labels + fb_label_count; ++i) 146433965Sjdp { 146533965Sjdp if (*i == label) 146633965Sjdp { 146733965Sjdp ++fb_label_instances[i - fb_labels]; 146833965Sjdp return; 146977298Sobrien } /* if we find it */ 147077298Sobrien } /* for each existing label */ 147133965Sjdp } 147233965Sjdp 147377298Sobrien /* If we get to here, we don't have label listed yet. */ 147433965Sjdp 147533965Sjdp if (fb_labels == NULL) 147633965Sjdp { 147733965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 147833965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 147933965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 148033965Sjdp fb_label_count = FB_LABEL_SPECIAL; 148133965Sjdp 148233965Sjdp } 148333965Sjdp else if (fb_label_count == fb_label_max) 148433965Sjdp { 148533965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 148633965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 148733965Sjdp fb_label_max * sizeof (long)); 148833965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 148933965Sjdp fb_label_max * sizeof (long)); 149077298Sobrien } /* if we needed to grow */ 149133965Sjdp 149233965Sjdp fb_labels[fb_label_count] = label; 149333965Sjdp fb_label_instances[fb_label_count] = 1; 149433965Sjdp ++fb_label_count; 149533965Sjdp} 149633965Sjdp 149777298Sobrienstatic long 149833965Sjdpfb_label_instance (label) 149933965Sjdp long label; 150033965Sjdp{ 150133965Sjdp long *i; 150233965Sjdp 150333965Sjdp if (label < FB_LABEL_SPECIAL) 150433965Sjdp { 150533965Sjdp return (fb_low_counter[label]); 150633965Sjdp } 150733965Sjdp 150833965Sjdp if (fb_labels != NULL) 150933965Sjdp { 151033965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 151133965Sjdp i < fb_labels + fb_label_count; ++i) 151233965Sjdp { 151333965Sjdp if (*i == label) 151433965Sjdp { 151533965Sjdp return (fb_label_instances[i - fb_labels]); 151677298Sobrien } /* if we find it */ 151777298Sobrien } /* for each existing label */ 151833965Sjdp } 151933965Sjdp 152033965Sjdp /* We didn't find the label, so this must be a reference to the 152133965Sjdp first instance. */ 152233965Sjdp return 0; 152333965Sjdp} 152433965Sjdp 152577298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 152633965Sjdp 152777298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 152877298Sobrien where n is the label number and m is the instance number. "L" makes 152977298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 153077298Sobrien ordinary symbol SHOULD get the same name as a local label 153177298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 153277298Sobrien 153377298Sobrien dollar labels get the same treatment, except that ^A is used in 153477298Sobrien place of ^B. */ 153577298Sobrien 153677298Sobrienchar * /* Return local label name. */ 153733965Sjdpfb_label_name (n, augend) 153877298Sobrien long n; /* We just saw "n:", "nf" or "nb" : n a number. */ 153977298Sobrien long augend; /* 0 for nb, 1 for n:, nf. */ 154033965Sjdp{ 154133965Sjdp long i; 154277298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 154333965Sjdp static char symbol_name_build[24]; 154433965Sjdp register char *p; 154533965Sjdp register char *q; 154677298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 154733965Sjdp 154833965Sjdp know (n >= 0); 154933965Sjdp know (augend == 0 || augend == 1); 155033965Sjdp p = symbol_name_build; 155177298Sobrien#ifdef LOCAL_LABEL_PREFIX 155277298Sobrien *p++ = LOCAL_LABEL_PREFIX; 155377298Sobrien#endif 155433965Sjdp *p++ = 'L'; 155533965Sjdp 155677298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 155777298Sobrien /* Label number. */ 155833965Sjdp q = symbol_name_temporary; 155933965Sjdp for (*q++ = 0, i = n; i; ++q) 156033965Sjdp { 156133965Sjdp *q = i % 10 + '0'; 156233965Sjdp i /= 10; 156333965Sjdp } 156433965Sjdp while ((*p = *--q) != '\0') 156533965Sjdp ++p; 156633965Sjdp 156777298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 156833965Sjdp 156977298Sobrien /* Instance number. */ 157033965Sjdp q = symbol_name_temporary; 157133965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 157233965Sjdp { 157333965Sjdp *q = i % 10 + '0'; 157433965Sjdp i /= 10; 157533965Sjdp } 157633965Sjdp while ((*p++ = *--q) != '\0');; 157733965Sjdp 157877298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 157933965Sjdp return (symbol_name_build); 158077298Sobrien} 158133965Sjdp 158277298Sobrien/* Decode name that may have been generated by foo_label_name() above. 158377298Sobrien If the name wasn't generated by foo_label_name(), then return it 158477298Sobrien unaltered. This is used for error messages. */ 158533965Sjdp 158633965Sjdpchar * 158733965Sjdpdecode_local_label_name (s) 158833965Sjdp char *s; 158933965Sjdp{ 159033965Sjdp char *p; 159133965Sjdp char *symbol_decode; 159233965Sjdp int label_number; 159333965Sjdp int instance_number; 159433965Sjdp char *type; 159578828Sobrien const char *message_format; 159677298Sobrien int index = 0; 159733965Sjdp 159877298Sobrien#ifdef LOCAL_LABEL_PREFIX 159977298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 160077298Sobrien ++index; 160177298Sobrien#endif 160277298Sobrien 160377298Sobrien if (s[index] != 'L') 160433965Sjdp return s; 160533965Sjdp 160689857Sobrien for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p) 160733965Sjdp label_number = (10 * label_number) + *p - '0'; 160833965Sjdp 160977298Sobrien if (*p == DOLLAR_LABEL_CHAR) 161033965Sjdp type = "dollar"; 161177298Sobrien else if (*p == LOCAL_LABEL_CHAR) 161233965Sjdp type = "fb"; 161333965Sjdp else 161433965Sjdp return s; 161533965Sjdp 161689857Sobrien for (instance_number = 0, p++; ISDIGIT (*p); ++p) 161733965Sjdp instance_number = (10 * instance_number) + *p - '0'; 161833965Sjdp 161978828Sobrien message_format = _("\"%d\" (instance number %d of a %s label)"); 162033965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 162133965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 162233965Sjdp 162333965Sjdp return symbol_decode; 162433965Sjdp} 162533965Sjdp 162633965Sjdp/* Get the value of a symbol. */ 162733965Sjdp 162833965SjdpvalueT 162933965SjdpS_GET_VALUE (s) 163033965Sjdp symbolS *s; 163133965Sjdp{ 163260484Sobrien#ifdef BFD_ASSEMBLER 163360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 163489857Sobrien return resolve_symbol_value (s); 163560484Sobrien#endif 163660484Sobrien 163789857Sobrien if (!s->sy_resolved) 163889857Sobrien { 163989857Sobrien valueT val = resolve_symbol_value (s); 164089857Sobrien if (!finalize_syms) 164189857Sobrien return val; 164289857Sobrien } 164333965Sjdp if (s->sy_value.X_op != O_constant) 164433965Sjdp { 164533965Sjdp static symbolS *recur; 164633965Sjdp 164733965Sjdp /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON 164833965Sjdp may call S_GET_VALUE. We use a static symbol to avoid the 164933965Sjdp immediate recursion. */ 165033965Sjdp if (recur == s) 165133965Sjdp return (valueT) s->sy_value.X_add_number; 165233965Sjdp recur = s; 165333965Sjdp if (! s->sy_resolved 165433965Sjdp || s->sy_value.X_op != O_symbol 165533965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 165689857Sobrien as_bad (_("attempt to get value of unresolved symbol `%s'"), 165733965Sjdp S_GET_NAME (s)); 165833965Sjdp recur = NULL; 165933965Sjdp } 166033965Sjdp return (valueT) s->sy_value.X_add_number; 166133965Sjdp} 166233965Sjdp 166333965Sjdp/* Set the value of a symbol. */ 166433965Sjdp 166533965Sjdpvoid 166633965SjdpS_SET_VALUE (s, val) 166733965Sjdp symbolS *s; 166833965Sjdp valueT val; 166933965Sjdp{ 167060484Sobrien#ifdef BFD_ASSEMBLER 167160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 167260484Sobrien { 167389857Sobrien ((struct local_symbol *) s)->lsy_value = val; 167460484Sobrien return; 167560484Sobrien } 167660484Sobrien#endif 167760484Sobrien 167833965Sjdp s->sy_value.X_op = O_constant; 167933965Sjdp s->sy_value.X_add_number = (offsetT) val; 168033965Sjdp s->sy_value.X_unsigned = 0; 168133965Sjdp} 168233965Sjdp 168333965Sjdpvoid 168433965Sjdpcopy_symbol_attributes (dest, src) 168533965Sjdp symbolS *dest, *src; 168633965Sjdp{ 168760484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 168860484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 168960484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 169060484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 169160484Sobrien 169233965Sjdp#ifdef BFD_ASSEMBLER 169333965Sjdp /* In an expression, transfer the settings of these flags. 169433965Sjdp The user can override later, of course. */ 169538889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 169633965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 169733965Sjdp#endif 169833965Sjdp 169933965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 170033965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 170133965Sjdp#endif 170233965Sjdp} 170333965Sjdp 170433965Sjdp#ifdef BFD_ASSEMBLER 170533965Sjdp 170633965Sjdpint 170760484SobrienS_IS_FUNCTION (s) 170860484Sobrien symbolS *s; 170960484Sobrien{ 171060484Sobrien flagword flags; 171160484Sobrien 171260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 171360484Sobrien return 0; 171460484Sobrien 171560484Sobrien flags = s->bsym->flags; 171660484Sobrien 171760484Sobrien return (flags & BSF_FUNCTION) != 0; 171860484Sobrien} 171960484Sobrien 172060484Sobrienint 172133965SjdpS_IS_EXTERNAL (s) 172233965Sjdp symbolS *s; 172333965Sjdp{ 172460484Sobrien flagword flags; 172533965Sjdp 172660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 172760484Sobrien return 0; 172860484Sobrien 172960484Sobrien flags = s->bsym->flags; 173060484Sobrien 173177298Sobrien /* Sanity check. */ 173238889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 173333965Sjdp abort (); 173433965Sjdp 173533965Sjdp return (flags & BSF_GLOBAL) != 0; 173633965Sjdp} 173733965Sjdp 173833965Sjdpint 173933965SjdpS_IS_WEAK (s) 174033965Sjdp symbolS *s; 174133965Sjdp{ 174260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 174360484Sobrien return 0; 174433965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 174533965Sjdp} 174633965Sjdp 174733965Sjdpint 174833965SjdpS_IS_COMMON (s) 174933965Sjdp symbolS *s; 175033965Sjdp{ 175160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 175260484Sobrien return 0; 175333965Sjdp return bfd_is_com_section (s->bsym->section); 175433965Sjdp} 175533965Sjdp 175633965Sjdpint 175733965SjdpS_IS_DEFINED (s) 175833965Sjdp symbolS *s; 175933965Sjdp{ 176060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 176160484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 176233965Sjdp return s->bsym->section != undefined_section; 176333965Sjdp} 176433965Sjdp 176533965Sjdpint 176633965SjdpS_IS_DEBUG (s) 176733965Sjdp symbolS *s; 176833965Sjdp{ 176960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 177060484Sobrien return 0; 177133965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 177233965Sjdp return 1; 177333965Sjdp return 0; 177433965Sjdp} 177533965Sjdp 177633965Sjdpint 177733965SjdpS_IS_LOCAL (s) 177833965Sjdp symbolS *s; 177933965Sjdp{ 178060484Sobrien flagword flags; 178133965Sjdp const char *name; 178233965Sjdp 178360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 178460484Sobrien return 1; 178560484Sobrien 178660484Sobrien flags = s->bsym->flags; 178760484Sobrien 178877298Sobrien /* Sanity check. */ 178938889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 179033965Sjdp abort (); 179133965Sjdp 179233965Sjdp if (bfd_get_section (s->bsym) == reg_section) 179333965Sjdp return 1; 179433965Sjdp 179538889Sjdp if (flag_strip_local_absolute 179638889Sjdp && (flags & BSF_GLOBAL) == 0 179738889Sjdp && bfd_get_section (s->bsym) == absolute_section) 179838889Sjdp return 1; 179938889Sjdp 180033965Sjdp name = S_GET_NAME (s); 180133965Sjdp return (name != NULL 180233965Sjdp && ! S_IS_DEBUG (s) 180377298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 180477298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 180533965Sjdp || (! flag_keep_locals 180633965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 180733965Sjdp || (flag_mri 180833965Sjdp && name[0] == '?' 180933965Sjdp && name[1] == '?'))))); 181033965Sjdp} 181133965Sjdp 181233965Sjdpint 181333965SjdpS_IS_EXTERN (s) 181433965Sjdp symbolS *s; 181533965Sjdp{ 181633965Sjdp return S_IS_EXTERNAL (s); 181733965Sjdp} 181833965Sjdp 181933965Sjdpint 182033965SjdpS_IS_STABD (s) 182133965Sjdp symbolS *s; 182233965Sjdp{ 182333965Sjdp return S_GET_NAME (s) == 0; 182433965Sjdp} 182533965Sjdp 1826104834Sobrienconst char * 182733965SjdpS_GET_NAME (s) 182833965Sjdp symbolS *s; 182933965Sjdp{ 183060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 183160484Sobrien return ((struct local_symbol *) s)->lsy_name; 183233965Sjdp return s->bsym->name; 183333965Sjdp} 183433965Sjdp 183533965SjdpsegT 183633965SjdpS_GET_SEGMENT (s) 183733965Sjdp symbolS *s; 183833965Sjdp{ 183960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 184060484Sobrien return ((struct local_symbol *) s)->lsy_section; 184133965Sjdp return s->bsym->section; 184233965Sjdp} 184333965Sjdp 184433965Sjdpvoid 184533965SjdpS_SET_SEGMENT (s, seg) 184633965Sjdp symbolS *s; 184733965Sjdp segT seg; 184833965Sjdp{ 184938889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 185038889Sjdp faults assigning back to const global symbols such as *ABS*, but it 185138889Sjdp shouldn't happen anyway. */ 185238889Sjdp 185360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 185460484Sobrien { 185560484Sobrien if (seg == reg_section) 185660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 185760484Sobrien else 185860484Sobrien { 185960484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 186060484Sobrien return; 186160484Sobrien } 186260484Sobrien } 186360484Sobrien 186438889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 186538889Sjdp { 186638889Sjdp if (s->bsym->section != seg) 186777298Sobrien abort (); 186838889Sjdp } 186938889Sjdp else 187038889Sjdp s->bsym->section = seg; 187133965Sjdp} 187233965Sjdp 187333965Sjdpvoid 187433965SjdpS_SET_EXTERNAL (s) 187533965Sjdp symbolS *s; 187633965Sjdp{ 187760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 187860484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 187933965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 188033965Sjdp { 188133965Sjdp /* Let .weak override .global. */ 188233965Sjdp return; 188333965Sjdp } 188478828Sobrien if (s->bsym->flags & BSF_SECTION_SYM) 188578828Sobrien { 188678828Sobrien char * file; 188778828Sobrien unsigned int line; 1888104834Sobrien 188978828Sobrien /* Do not reassign section symbols. */ 189078828Sobrien as_where (& file, & line); 189178828Sobrien as_warn_where (file, line, 189289857Sobrien _("section symbols are already global")); 189378828Sobrien return; 189478828Sobrien } 189533965Sjdp s->bsym->flags |= BSF_GLOBAL; 189677298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 189733965Sjdp} 189833965Sjdp 189933965Sjdpvoid 190033965SjdpS_CLEAR_EXTERNAL (s) 190133965Sjdp symbolS *s; 190233965Sjdp{ 190360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 190460484Sobrien return; 190533965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 190633965Sjdp { 190733965Sjdp /* Let .weak override. */ 190833965Sjdp return; 190933965Sjdp } 191033965Sjdp s->bsym->flags |= BSF_LOCAL; 191177298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 191233965Sjdp} 191333965Sjdp 191433965Sjdpvoid 191533965SjdpS_SET_WEAK (s) 191633965Sjdp symbolS *s; 191733965Sjdp{ 191860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 191960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 192033965Sjdp s->bsym->flags |= BSF_WEAK; 192177298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 192233965Sjdp} 192333965Sjdp 192433965Sjdpvoid 192533965SjdpS_SET_NAME (s, name) 192633965Sjdp symbolS *s; 192733965Sjdp char *name; 192833965Sjdp{ 192960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 193060484Sobrien { 193160484Sobrien ((struct local_symbol *) s)->lsy_name = name; 193260484Sobrien return; 193360484Sobrien } 193433965Sjdp s->bsym->name = name; 193533965Sjdp} 193633965Sjdp#endif /* BFD_ASSEMBLER */ 193733965Sjdp 193860484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS 193960484Sobrien 194060484Sobrien/* Return the previous symbol in a chain. */ 194160484Sobrien 194260484SobriensymbolS * 194360484Sobriensymbol_previous (s) 194460484Sobrien symbolS *s; 194560484Sobrien{ 194660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 194760484Sobrien abort (); 194860484Sobrien return s->sy_previous; 194960484Sobrien} 195060484Sobrien 195160484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */ 195260484Sobrien 195360484Sobrien/* Return the next symbol in a chain. */ 195460484Sobrien 195560484SobriensymbolS * 195660484Sobriensymbol_next (s) 195760484Sobrien symbolS *s; 195860484Sobrien{ 195960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 196060484Sobrien abort (); 196160484Sobrien return s->sy_next; 196260484Sobrien} 196360484Sobrien 196460484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 196560484Sobrien 196660484SobrienexpressionS * 196760484Sobriensymbol_get_value_expression (s) 196860484Sobrien symbolS *s; 196960484Sobrien{ 197060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 197260484Sobrien return &s->sy_value; 197360484Sobrien} 197460484Sobrien 197560484Sobrien/* Set the value of a symbol to an expression. */ 197660484Sobrien 197733965Sjdpvoid 197860484Sobriensymbol_set_value_expression (s, exp) 197960484Sobrien symbolS *s; 198060484Sobrien const expressionS *exp; 198160484Sobrien{ 198260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 198360484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 198460484Sobrien s->sy_value = *exp; 198560484Sobrien} 198660484Sobrien 198760484Sobrien/* Set the frag of a symbol. */ 198860484Sobrien 198960484Sobrienvoid 199060484Sobriensymbol_set_frag (s, f) 199160484Sobrien symbolS *s; 199260484Sobrien fragS *f; 199360484Sobrien{ 199460484Sobrien#ifdef BFD_ASSEMBLER 199560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 199660484Sobrien { 199760484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 199860484Sobrien return; 199960484Sobrien } 200060484Sobrien#endif 200160484Sobrien s->sy_frag = f; 200260484Sobrien} 200360484Sobrien 200460484Sobrien/* Return the frag of a symbol. */ 200560484Sobrien 200660484SobrienfragS * 200760484Sobriensymbol_get_frag (s) 200860484Sobrien symbolS *s; 200960484Sobrien{ 201060484Sobrien#ifdef BFD_ASSEMBLER 201160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 201260484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 201360484Sobrien#endif 201460484Sobrien return s->sy_frag; 201560484Sobrien} 201660484Sobrien 201760484Sobrien/* Mark a symbol as having been used. */ 201860484Sobrien 201960484Sobrienvoid 202060484Sobriensymbol_mark_used (s) 202160484Sobrien symbolS *s; 202260484Sobrien{ 202360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202460484Sobrien return; 202560484Sobrien s->sy_used = 1; 202660484Sobrien} 202760484Sobrien 202860484Sobrien/* Clear the mark of whether a symbol has been used. */ 202960484Sobrien 203060484Sobrienvoid 203160484Sobriensymbol_clear_used (s) 203260484Sobrien symbolS *s; 203360484Sobrien{ 203460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 203560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 203660484Sobrien s->sy_used = 0; 203760484Sobrien} 203860484Sobrien 203960484Sobrien/* Return whether a symbol has been used. */ 204060484Sobrien 204160484Sobrienint 204260484Sobriensymbol_used_p (s) 204360484Sobrien symbolS *s; 204460484Sobrien{ 204560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 204660484Sobrien return 1; 204760484Sobrien return s->sy_used; 204860484Sobrien} 204960484Sobrien 205060484Sobrien/* Mark a symbol as having been used in a reloc. */ 205160484Sobrien 205260484Sobrienvoid 205360484Sobriensymbol_mark_used_in_reloc (s) 205460484Sobrien symbolS *s; 205560484Sobrien{ 205660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 205760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 205860484Sobrien s->sy_used_in_reloc = 1; 205960484Sobrien} 206060484Sobrien 206160484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 206260484Sobrien 206360484Sobrienvoid 206460484Sobriensymbol_clear_used_in_reloc (s) 206560484Sobrien symbolS *s; 206660484Sobrien{ 206760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 206860484Sobrien return; 206960484Sobrien s->sy_used_in_reloc = 0; 207060484Sobrien} 207160484Sobrien 207260484Sobrien/* Return whether a symbol has been used in a reloc. */ 207360484Sobrien 207460484Sobrienint 207560484Sobriensymbol_used_in_reloc_p (s) 207660484Sobrien symbolS *s; 207760484Sobrien{ 207860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207960484Sobrien return 0; 208060484Sobrien return s->sy_used_in_reloc; 208160484Sobrien} 208260484Sobrien 208360484Sobrien/* Mark a symbol as an MRI common symbol. */ 208460484Sobrien 208560484Sobrienvoid 208660484Sobriensymbol_mark_mri_common (s) 208760484Sobrien symbolS *s; 208860484Sobrien{ 208960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 209060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 209160484Sobrien s->sy_mri_common = 1; 209260484Sobrien} 209360484Sobrien 209460484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 209560484Sobrien 209660484Sobrienvoid 209760484Sobriensymbol_clear_mri_common (s) 209860484Sobrien symbolS *s; 209960484Sobrien{ 210060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 210160484Sobrien return; 210260484Sobrien s->sy_mri_common = 0; 210360484Sobrien} 210460484Sobrien 210560484Sobrien/* Return whether a symbol is an MRI common symbol. */ 210660484Sobrien 210760484Sobrienint 210860484Sobriensymbol_mri_common_p (s) 210960484Sobrien symbolS *s; 211060484Sobrien{ 211160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 211260484Sobrien return 0; 211360484Sobrien return s->sy_mri_common; 211460484Sobrien} 211560484Sobrien 211660484Sobrien/* Mark a symbol as having been written. */ 211760484Sobrien 211860484Sobrienvoid 211960484Sobriensymbol_mark_written (s) 212060484Sobrien symbolS *s; 212160484Sobrien{ 212260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212360484Sobrien return; 212460484Sobrien s->written = 1; 212560484Sobrien} 212660484Sobrien 212760484Sobrien/* Clear the mark of whether a symbol has been written. */ 212860484Sobrien 212960484Sobrienvoid 213060484Sobriensymbol_clear_written (s) 213160484Sobrien symbolS *s; 213260484Sobrien{ 213360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213460484Sobrien return; 213560484Sobrien s->written = 0; 213660484Sobrien} 213760484Sobrien 213860484Sobrien/* Return whether a symbol has been written. */ 213960484Sobrien 214060484Sobrienint 214160484Sobriensymbol_written_p (s) 214260484Sobrien symbolS *s; 214360484Sobrien{ 214460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 214560484Sobrien return 0; 214660484Sobrien return s->written; 214760484Sobrien} 214860484Sobrien 214960484Sobrien/* Mark a symbol has having been resolved. */ 215060484Sobrien 215160484Sobrienvoid 215260484Sobriensymbol_mark_resolved (s) 215360484Sobrien symbolS *s; 215460484Sobrien{ 215560484Sobrien#ifdef BFD_ASSEMBLER 215660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 215760484Sobrien { 215860484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 215960484Sobrien return; 216060484Sobrien } 216160484Sobrien#endif 216260484Sobrien s->sy_resolved = 1; 216360484Sobrien} 216460484Sobrien 216560484Sobrien/* Return whether a symbol has been resolved. */ 216660484Sobrien 216760484Sobrienint 216860484Sobriensymbol_resolved_p (s) 216960484Sobrien symbolS *s; 217060484Sobrien{ 217160484Sobrien#ifdef BFD_ASSEMBLER 217260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217360484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 217460484Sobrien#endif 217560484Sobrien return s->sy_resolved; 217660484Sobrien} 217760484Sobrien 217860484Sobrien/* Return whether a symbol is a section symbol. */ 217960484Sobrien 218060484Sobrienint 218160484Sobriensymbol_section_p (s) 218260484Sobrien symbolS *s ATTRIBUTE_UNUSED; 218360484Sobrien{ 218460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 218560484Sobrien return 0; 218660484Sobrien#ifdef BFD_ASSEMBLER 218760484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 218860484Sobrien#else 218977298Sobrien /* FIXME. */ 219060484Sobrien return 0; 219160484Sobrien#endif 219260484Sobrien} 219360484Sobrien 219460484Sobrien/* Return whether a symbol is equated to another symbol. */ 219560484Sobrien 219660484Sobrienint 219760484Sobriensymbol_equated_p (s) 219860484Sobrien symbolS *s; 219960484Sobrien{ 220060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 220160484Sobrien return 0; 220260484Sobrien return s->sy_value.X_op == O_symbol; 220360484Sobrien} 220460484Sobrien 220589857Sobrien/* Return whether a symbol is equated to another symbol, and should be 220689857Sobrien treated specially when writing out relocs. */ 220789857Sobrien 220889857Sobrienint 220989857Sobriensymbol_equated_reloc_p (s) 221089857Sobrien symbolS *s; 221189857Sobrien{ 221289857Sobrien if (LOCAL_SYMBOL_CHECK (s)) 221389857Sobrien return 0; 221489857Sobrien /* X_op_symbol, normally not used for O_symbol, is set by 221589857Sobrien resolve_symbol_value to flag expression syms that have been 221689857Sobrien equated. */ 221789857Sobrien return (s->sy_value.X_op == O_symbol 221889857Sobrien && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL) 221989857Sobrien || ! S_IS_DEFINED (s) 222089857Sobrien || S_IS_COMMON (s))); 222189857Sobrien} 222289857Sobrien 222360484Sobrien/* Return whether a symbol has a constant value. */ 222460484Sobrien 222560484Sobrienint 222660484Sobriensymbol_constant_p (s) 222760484Sobrien symbolS *s; 222860484Sobrien{ 222960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 223060484Sobrien return 1; 223160484Sobrien return s->sy_value.X_op == O_constant; 223260484Sobrien} 223360484Sobrien 223460484Sobrien#ifdef BFD_ASSEMBLER 223560484Sobrien 223660484Sobrien/* Return the BFD symbol for a symbol. */ 223760484Sobrien 223860484Sobrienasymbol * 223960484Sobriensymbol_get_bfdsym (s) 224060484Sobrien symbolS *s; 224160484Sobrien{ 224260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 224360484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 224460484Sobrien return s->bsym; 224560484Sobrien} 224660484Sobrien 224760484Sobrien/* Set the BFD symbol for a symbol. */ 224860484Sobrien 224960484Sobrienvoid 225060484Sobriensymbol_set_bfdsym (s, bsym) 225160484Sobrien symbolS *s; 225260484Sobrien asymbol *bsym; 225360484Sobrien{ 225460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 225560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 225660484Sobrien s->bsym = bsym; 225760484Sobrien} 225860484Sobrien 225960484Sobrien#endif /* BFD_ASSEMBLER */ 226060484Sobrien 226160484Sobrien#ifdef OBJ_SYMFIELD_TYPE 226260484Sobrien 226360484Sobrien/* Get a pointer to the object format information for a symbol. */ 226460484Sobrien 226560484SobrienOBJ_SYMFIELD_TYPE * 226660484Sobriensymbol_get_obj (s) 226760484Sobrien symbolS *s; 226860484Sobrien{ 226960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 227060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 227160484Sobrien return &s->sy_obj; 227260484Sobrien} 227360484Sobrien 227460484Sobrien/* Set the object format information for a symbol. */ 227560484Sobrien 227660484Sobrienvoid 227760484Sobriensymbol_set_obj (s, o) 227860484Sobrien symbolS *s; 227960484Sobrien OBJ_SYMFIELD_TYPE *o; 228060484Sobrien{ 228160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 228260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 228360484Sobrien s->sy_obj = *o; 228460484Sobrien} 228560484Sobrien 228660484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 228760484Sobrien 228860484Sobrien#ifdef TC_SYMFIELD_TYPE 228960484Sobrien 229060484Sobrien/* Get a pointer to the processor information for a symbol. */ 229160484Sobrien 229260484SobrienTC_SYMFIELD_TYPE * 229360484Sobriensymbol_get_tc (s) 229460484Sobrien symbolS *s; 229560484Sobrien{ 229660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 229760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 229860484Sobrien return &s->sy_tc; 229960484Sobrien} 230060484Sobrien 230160484Sobrien/* Set the processor information for a symbol. */ 230260484Sobrien 230360484Sobrienvoid 230460484Sobriensymbol_set_tc (s, o) 230560484Sobrien symbolS *s; 230660484Sobrien TC_SYMFIELD_TYPE *o; 230760484Sobrien{ 230860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 230960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 231060484Sobrien s->sy_tc = *o; 231160484Sobrien} 231260484Sobrien 231360484Sobrien#endif /* TC_SYMFIELD_TYPE */ 231460484Sobrien 231560484Sobrienvoid 231633965Sjdpsymbol_begin () 231733965Sjdp{ 231833965Sjdp symbol_lastP = NULL; 231977298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 232033965Sjdp sy_hash = hash_new (); 232160484Sobrien#ifdef BFD_ASSEMBLER 232260484Sobrien local_hash = hash_new (); 232360484Sobrien#endif 232433965Sjdp 232533965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 232633965Sjdp#ifdef BFD_ASSEMBLER 232733965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 232833965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 232933965Sjdp#endif 233033965Sjdp#else 233177298Sobrien /* Can't initialise a union. Sigh. */ 233233965Sjdp S_SET_SEGMENT (&abs_symbol, absolute_section); 233333965Sjdp#endif 233433965Sjdp abs_symbol.sy_value.X_op = O_constant; 233533965Sjdp abs_symbol.sy_frag = &zero_address_frag; 233633965Sjdp 233733965Sjdp if (LOCAL_LABELS_FB) 233833965Sjdp fb_label_init (); 233933965Sjdp} 234033965Sjdp 234133965Sjdpint indent_level; 234233965Sjdp 234360484Sobrien/* Maximum indent level. 234460484Sobrien Available for modification inside a gdb session. */ 234560484Sobrienint max_indent_level = 8; 234660484Sobrien 234733965Sjdp#if 0 234833965Sjdp 234933965Sjdpstatic void 235033965Sjdpindent () 235133965Sjdp{ 235233965Sjdp printf ("%*s", indent_level * 4, ""); 235333965Sjdp} 235433965Sjdp 235533965Sjdp#endif 235633965Sjdp 235733965Sjdpvoid 235833965Sjdpprint_symbol_value_1 (file, sym) 235933965Sjdp FILE *file; 236033965Sjdp symbolS *sym; 236133965Sjdp{ 236233965Sjdp const char *name = S_GET_NAME (sym); 236333965Sjdp if (!name || !name[0]) 236433965Sjdp name = "(unnamed)"; 236533965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 236660484Sobrien 236760484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 236860484Sobrien { 236960484Sobrien#ifdef BFD_ASSEMBLER 237060484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 237160484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 237260484Sobrien && local_symbol_get_frag (locsym) != NULL) 237360484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 237460484Sobrien if (local_symbol_resolved_p (locsym)) 237560484Sobrien fprintf (file, " resolved"); 237660484Sobrien fprintf (file, " local"); 237760484Sobrien#endif 237860484Sobrien } 237960484Sobrien else 238060484Sobrien { 238160484Sobrien if (sym->sy_frag != &zero_address_frag) 238260484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 238360484Sobrien if (sym->written) 238460484Sobrien fprintf (file, " written"); 238560484Sobrien if (sym->sy_resolved) 238660484Sobrien fprintf (file, " resolved"); 238760484Sobrien else if (sym->sy_resolving) 238860484Sobrien fprintf (file, " resolving"); 238960484Sobrien if (sym->sy_used_in_reloc) 239060484Sobrien fprintf (file, " used-in-reloc"); 239160484Sobrien if (sym->sy_used) 239260484Sobrien fprintf (file, " used"); 239360484Sobrien if (S_IS_LOCAL (sym)) 239460484Sobrien fprintf (file, " local"); 239560484Sobrien if (S_IS_EXTERN (sym)) 239660484Sobrien fprintf (file, " extern"); 239760484Sobrien if (S_IS_DEBUG (sym)) 239860484Sobrien fprintf (file, " debug"); 239960484Sobrien if (S_IS_DEFINED (sym)) 240060484Sobrien fprintf (file, " defined"); 240160484Sobrien } 240233965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 240360484Sobrien if (symbol_resolved_p (sym)) 240433965Sjdp { 240533965Sjdp segT s = S_GET_SEGMENT (sym); 240633965Sjdp 240733965Sjdp if (s != undefined_section 2408104834Sobrien && s != expr_section) 240933965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 241033965Sjdp } 241160484Sobrien else if (indent_level < max_indent_level 241260484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 241333965Sjdp { 241433965Sjdp indent_level++; 241533965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 241660484Sobrien#ifdef BFD_ASSEMBLER 241760484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 241860484Sobrien fprintf (file, "constant %lx", 241989857Sobrien (long) ((struct local_symbol *) sym)->lsy_value); 242060484Sobrien else 242160484Sobrien#endif 242260484Sobrien print_expr_1 (file, &sym->sy_value); 242333965Sjdp fprintf (file, ">"); 242433965Sjdp indent_level--; 242533965Sjdp } 242633965Sjdp fflush (file); 242733965Sjdp} 242833965Sjdp 242933965Sjdpvoid 243033965Sjdpprint_symbol_value (sym) 243133965Sjdp symbolS *sym; 243233965Sjdp{ 243333965Sjdp indent_level = 0; 243433965Sjdp print_symbol_value_1 (stderr, sym); 243533965Sjdp fprintf (stderr, "\n"); 243633965Sjdp} 243733965Sjdp 243860484Sobrienstatic void 243960484Sobrienprint_binary (file, name, exp) 244060484Sobrien FILE *file; 244177298Sobrien const char *name; 244260484Sobrien expressionS *exp; 244360484Sobrien{ 244460484Sobrien indent_level++; 244560484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 244660484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 244760484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 244860484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 244960484Sobrien fprintf (file, ">"); 245060484Sobrien indent_level--; 245160484Sobrien} 245260484Sobrien 245333965Sjdpvoid 245433965Sjdpprint_expr_1 (file, exp) 245533965Sjdp FILE *file; 245633965Sjdp expressionS *exp; 245733965Sjdp{ 245833965Sjdp fprintf (file, "expr %lx ", (long) exp); 245933965Sjdp switch (exp->X_op) 246033965Sjdp { 246133965Sjdp case O_illegal: 246233965Sjdp fprintf (file, "illegal"); 246333965Sjdp break; 246433965Sjdp case O_absent: 246533965Sjdp fprintf (file, "absent"); 246633965Sjdp break; 246733965Sjdp case O_constant: 246833965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 246933965Sjdp break; 247033965Sjdp case O_symbol: 247133965Sjdp indent_level++; 247233965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 247333965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 247433965Sjdp fprintf (file, ">"); 247533965Sjdp maybe_print_addnum: 247633965Sjdp if (exp->X_add_number) 247733965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 247833965Sjdp (long) exp->X_add_number); 247933965Sjdp indent_level--; 248033965Sjdp break; 248133965Sjdp case O_register: 248233965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 248333965Sjdp break; 248433965Sjdp case O_big: 248533965Sjdp fprintf (file, "big"); 248633965Sjdp break; 248733965Sjdp case O_uminus: 248833965Sjdp fprintf (file, "uminus -<"); 248933965Sjdp indent_level++; 249033965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 249133965Sjdp fprintf (file, ">"); 249233965Sjdp goto maybe_print_addnum; 249333965Sjdp case O_bit_not: 249433965Sjdp fprintf (file, "bit_not"); 249533965Sjdp break; 249633965Sjdp case O_multiply: 249760484Sobrien print_binary (file, "multiply", exp); 249833965Sjdp break; 249933965Sjdp case O_divide: 250060484Sobrien print_binary (file, "divide", exp); 250133965Sjdp break; 250233965Sjdp case O_modulus: 250360484Sobrien print_binary (file, "modulus", exp); 250433965Sjdp break; 250533965Sjdp case O_left_shift: 250660484Sobrien print_binary (file, "lshift", exp); 250733965Sjdp break; 250833965Sjdp case O_right_shift: 250960484Sobrien print_binary (file, "rshift", exp); 251033965Sjdp break; 251133965Sjdp case O_bit_inclusive_or: 251260484Sobrien print_binary (file, "bit_ior", exp); 251333965Sjdp break; 251433965Sjdp case O_bit_exclusive_or: 251560484Sobrien print_binary (file, "bit_xor", exp); 251633965Sjdp break; 251733965Sjdp case O_bit_and: 251860484Sobrien print_binary (file, "bit_and", exp); 251933965Sjdp break; 252033965Sjdp case O_eq: 252160484Sobrien print_binary (file, "eq", exp); 252233965Sjdp break; 252333965Sjdp case O_ne: 252460484Sobrien print_binary (file, "ne", exp); 252533965Sjdp break; 252633965Sjdp case O_lt: 252760484Sobrien print_binary (file, "lt", exp); 252833965Sjdp break; 252933965Sjdp case O_le: 253060484Sobrien print_binary (file, "le", exp); 253133965Sjdp break; 253233965Sjdp case O_ge: 253360484Sobrien print_binary (file, "ge", exp); 253433965Sjdp break; 253533965Sjdp case O_gt: 253660484Sobrien print_binary (file, "gt", exp); 253733965Sjdp break; 253833965Sjdp case O_logical_and: 253960484Sobrien print_binary (file, "logical_and", exp); 254033965Sjdp break; 254133965Sjdp case O_logical_or: 254260484Sobrien print_binary (file, "logical_or", exp); 254333965Sjdp break; 254433965Sjdp case O_add: 254533965Sjdp indent_level++; 254633965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 254733965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 254833965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 254933965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 255033965Sjdp fprintf (file, ">"); 255133965Sjdp goto maybe_print_addnum; 255233965Sjdp case O_subtract: 255333965Sjdp indent_level++; 255433965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 255533965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 255633965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 255733965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 255833965Sjdp fprintf (file, ">"); 255933965Sjdp goto maybe_print_addnum; 256033965Sjdp default: 256133965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 256233965Sjdp break; 256333965Sjdp } 256433965Sjdp fflush (stdout); 256533965Sjdp} 256633965Sjdp 256733965Sjdpvoid 256833965Sjdpprint_expr (exp) 256933965Sjdp expressionS *exp; 257033965Sjdp{ 257133965Sjdp print_expr_1 (stderr, exp); 257233965Sjdp fprintf (stderr, "\n"); 257333965Sjdp} 257433965Sjdp 257533965Sjdpvoid 257633965Sjdpsymbol_print_statistics (file) 257733965Sjdp FILE *file; 257833965Sjdp{ 257933965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 258060484Sobrien#ifdef BFD_ASSEMBLER 258160484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 258260484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 258360484Sobrien local_symbol_count, local_symbol_conversion_count); 258460484Sobrien#endif 258533965Sjdp} 2586