symbols.c revision 77298
133965Sjdp/* symbols.c -symbol table- 260484Sobrien Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 333965Sjdp Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GAS, the GNU Assembler. 633965Sjdp 733965Sjdp GAS is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2, or (at your option) 1033965Sjdp any later version. 1133965Sjdp 1233965Sjdp GAS is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1833965Sjdp along with GAS; see the file COPYING. If not, write to the Free 1933965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2033965Sjdp 02111-1307, USA. */ 2133965Sjdp 2277298Sobrien/* #define DEBUG_SYMS / * to debug symbol list maintenance. */ 2333965Sjdp 2433965Sjdp#include <ctype.h> 2533965Sjdp 2633965Sjdp#include "as.h" 2733965Sjdp 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 6333965Sjdpstatic void fb_label_init PARAMS ((void)); 6433965Sjdpstatic long dollar_label_instance PARAMS ((long)); 6533965Sjdpstatic long fb_label_instance PARAMS ((long)); 6633965Sjdp 6760484Sobrienstatic void print_binary PARAMS ((FILE *, const char *, expressionS *)); 6860484Sobrien 6977298Sobrien/* Return a pointer to a new symbol. Die if we can't make a new 7033965Sjdp symbol. Fill in the symbol's values. Add symbol to end of symbol 7133965Sjdp chain. 7277298Sobrien 7333965Sjdp This function should be called in the general case of creating a 7433965Sjdp symbol. However, if the output file symbol table has already been 7533965Sjdp set, and you are certain that this symbol won't be wanted in the 7633965Sjdp output file, you can call symbol_create. */ 7733965Sjdp 7833965SjdpsymbolS * 7933965Sjdpsymbol_new (name, segment, valu, frag) 8033965Sjdp const char *name; 8133965Sjdp segT segment; 8233965Sjdp valueT valu; 8333965Sjdp fragS *frag; 8433965Sjdp{ 8533965Sjdp symbolS *symbolP = symbol_create (name, segment, valu, frag); 8633965Sjdp 8777298Sobrien /* Link to end of symbol chain. */ 8833965Sjdp#ifdef BFD_ASSEMBLER 8933965Sjdp { 9033965Sjdp extern int symbol_table_frozen; 9133965Sjdp if (symbol_table_frozen) 9233965Sjdp abort (); 9333965Sjdp } 9433965Sjdp#endif 9533965Sjdp symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP); 9633965Sjdp 9733965Sjdp return symbolP; 9833965Sjdp} 9933965Sjdp 10060484Sobrien/* Save a symbol name on a permanent obstack, and convert it according 10160484Sobrien to the object file format. */ 10260484Sobrien 10360484Sobrienstatic char * 10460484Sobriensave_symbol_name (name) 10560484Sobrien const char *name; 10633965Sjdp{ 10733965Sjdp unsigned int name_length; 10860484Sobrien char *ret; 10933965Sjdp 11077298Sobrien name_length = strlen (name) + 1; /* +1 for \0. */ 11133965Sjdp obstack_grow (¬es, name, name_length); 11260484Sobrien ret = obstack_finish (¬es); 11360484Sobrien 11433965Sjdp#ifdef STRIP_UNDERSCORE 11560484Sobrien if (ret[0] == '_') 11660484Sobrien ++ret; 11733965Sjdp#endif 11833965Sjdp 11933965Sjdp#ifdef tc_canonicalize_symbol_name 12060484Sobrien ret = tc_canonicalize_symbol_name (ret); 12133965Sjdp#endif 12233965Sjdp 12333965Sjdp if (! symbols_case_sensitive) 12433965Sjdp { 12533965Sjdp unsigned char *s; 12633965Sjdp 12760484Sobrien for (s = (unsigned char *) ret; *s != '\0'; s++) 12833965Sjdp if (islower (*s)) 12933965Sjdp *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 * 20860484Sobrienlocal_symbol_make (name, section, offset, frag) 20960484Sobrien const char *name; 21060484Sobrien segT section; 21160484Sobrien valueT offset; 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); 22660484Sobrien ret->lsy_offset = offset; 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 24860484Sobrien ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset, 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 25760484Sobrien symbol_table_insert (ret); 25860484Sobrien 25960484Sobrien local_symbol_mark_converted (locsym); 26060484Sobrien local_symbol_set_real_symbol (locsym, ret); 26160484Sobrien 26260484Sobrien hash_jam (local_hash, locsym->lsy_name, NULL); 26360484Sobrien 26460484Sobrien return ret; 26560484Sobrien} 26660484Sobrien 26760484Sobrien#else /* ! BFD_ASSEMBLER */ 26860484Sobrien 26960484Sobrien#define LOCAL_SYMBOL_CHECK(s) 0 27060484Sobrien#define local_symbol_convert(s) ((symbolS *) s) 27160484Sobrien 27260484Sobrien#endif /* ! BFD_ASSEMBLER */ 27360484Sobrien 27477298Sobrien/* We have just seen "<name>:". 27577298Sobrien Creates a struct symbol unless it already exists. 27660484Sobrien 27777298Sobrien Gripes if we are redefining a symbol incompatibly (and ignores it). */ 27877298Sobrien 27933965SjdpsymbolS * 28077298Sobriencolon (sym_name) /* Just seen "x:" - rattle symbols & frags. */ 28177298Sobrien const char *sym_name; /* Symbol name, as a cannonical string. */ 28277298Sobrien /* We copy this string: OK to alter later. */ 28333965Sjdp{ 28477298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 28533965Sjdp 28633965Sjdp /* Sun local labels go out of scope whenever a non-local symbol is 28733965Sjdp defined. */ 28833965Sjdp if (LOCAL_LABELS_DOLLAR) 28933965Sjdp { 29033965Sjdp int local; 29133965Sjdp 29233965Sjdp#ifdef BFD_ASSEMBLER 29333965Sjdp local = bfd_is_local_label_name (stdoutput, sym_name); 29433965Sjdp#else 29533965Sjdp local = LOCAL_LABEL (sym_name); 29633965Sjdp#endif 29733965Sjdp 29833965Sjdp if (! local) 29933965Sjdp dollar_label_clear (); 30033965Sjdp } 30133965Sjdp 30233965Sjdp#ifndef WORKING_DOT_WORD 30333965Sjdp if (new_broken_words) 30433965Sjdp { 30533965Sjdp struct broken_word *a; 30633965Sjdp int possible_bytes; 30733965Sjdp fragS *frag_tmp; 30833965Sjdp char *frag_opcode; 30933965Sjdp 31033965Sjdp extern const int md_short_jump_size; 31133965Sjdp extern const int md_long_jump_size; 31233965Sjdp possible_bytes = (md_short_jump_size 31333965Sjdp + new_broken_words * md_long_jump_size); 31433965Sjdp 31533965Sjdp frag_tmp = frag_now; 31633965Sjdp frag_opcode = frag_var (rs_broken_word, 31733965Sjdp possible_bytes, 31833965Sjdp possible_bytes, 31933965Sjdp (relax_substateT) 0, 32033965Sjdp (symbolS *) broken_words, 32133965Sjdp (offsetT) 0, 32233965Sjdp NULL); 32333965Sjdp 32477298Sobrien /* We want to store the pointer to where to insert the jump 32577298Sobrien table in the fr_opcode of the rs_broken_word frag. This 32677298Sobrien requires a little hackery. */ 32733965Sjdp while (frag_tmp 32833965Sjdp && (frag_tmp->fr_type != rs_broken_word 32933965Sjdp || frag_tmp->fr_opcode)) 33033965Sjdp frag_tmp = frag_tmp->fr_next; 33133965Sjdp know (frag_tmp); 33233965Sjdp frag_tmp->fr_opcode = frag_opcode; 33333965Sjdp new_broken_words = 0; 33433965Sjdp 33533965Sjdp for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word) 33633965Sjdp a->dispfrag = frag_tmp; 33733965Sjdp } 33833965Sjdp#endif /* WORKING_DOT_WORD */ 33933965Sjdp 34033965Sjdp if ((symbolP = symbol_find (sym_name)) != 0) 34133965Sjdp { 34233965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION 34333965Sjdp if (RESOLVE_SYMBOL_REDEFINITION (symbolP)) 34433965Sjdp return symbolP; 34533965Sjdp#endif 34677298Sobrien /* Now check for undefined symbols. */ 34760484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 34833965Sjdp { 34960484Sobrien#ifdef BFD_ASSEMBLER 35060484Sobrien struct local_symbol *locsym = (struct local_symbol *) symbolP; 35160484Sobrien 35260484Sobrien if (locsym->lsy_section != undefined_section 35360484Sobrien && (local_symbol_get_frag (locsym) != frag_now 35460484Sobrien || locsym->lsy_section != now_seg 35560484Sobrien || locsym->lsy_offset != frag_now_fix ())) 35660484Sobrien { 35760484Sobrien as_bad (_("Symbol %s already defined."), sym_name); 35860484Sobrien return symbolP; 35960484Sobrien } 36060484Sobrien 36160484Sobrien locsym->lsy_section = now_seg; 36260484Sobrien local_symbol_set_frag (locsym, frag_now); 36360484Sobrien locsym->lsy_offset = frag_now_fix (); 36460484Sobrien#endif 36560484Sobrien } 36660484Sobrien else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 36760484Sobrien { 36833965Sjdp if (S_GET_VALUE (symbolP) == 0) 36933965Sjdp { 37033965Sjdp symbolP->sy_frag = frag_now; 37133965Sjdp#ifdef OBJ_VMS 37277298Sobrien S_SET_OTHER (symbolP, const_flag); 37333965Sjdp#endif 37433965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 37533965Sjdp S_SET_SEGMENT (symbolP, now_seg); 37633965Sjdp#ifdef N_UNDF 37733965Sjdp know (N_UNDF == 0); 37877298Sobrien#endif /* if we have one, it better be zero. */ 37933965Sjdp 38033965Sjdp } 38133965Sjdp else 38233965Sjdp { 38377298Sobrien /* There are still several cases to check: 38433965Sjdp 38577298Sobrien A .comm/.lcomm symbol being redefined as initialized 38677298Sobrien data is OK 38777298Sobrien 38877298Sobrien A .comm/.lcomm symbol being redefined with a larger 38977298Sobrien size is also OK 39077298Sobrien 39177298Sobrien This only used to be allowed on VMS gas, but Sun cc 39277298Sobrien on the sparc also depends on it. */ 39377298Sobrien 39433965Sjdp if (((!S_IS_DEBUG (symbolP) 39533965Sjdp && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 39633965Sjdp && S_IS_EXTERNAL (symbolP)) 39733965Sjdp || S_GET_SEGMENT (symbolP) == bss_section) 39833965Sjdp && (now_seg == data_section 39933965Sjdp || now_seg == S_GET_SEGMENT (symbolP))) 40033965Sjdp { 40177298Sobrien /* Select which of the 2 cases this is. */ 40233965Sjdp if (now_seg != data_section) 40333965Sjdp { 40477298Sobrien /* New .comm for prev .comm symbol. 40577298Sobrien 40677298Sobrien If the new size is larger we just change its 40777298Sobrien value. If the new size is smaller, we ignore 40877298Sobrien this symbol. */ 40933965Sjdp if (S_GET_VALUE (symbolP) 41033965Sjdp < ((unsigned) frag_now_fix ())) 41133965Sjdp { 41233965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 41333965Sjdp } 41433965Sjdp } 41533965Sjdp else 41633965Sjdp { 41733965Sjdp /* It is a .comm/.lcomm being converted to initialized 41833965Sjdp data. */ 41933965Sjdp symbolP->sy_frag = frag_now; 42033965Sjdp#ifdef OBJ_VMS 42177298Sobrien S_SET_OTHER (symbolP, const_flag); 42233965Sjdp#endif 42333965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 42477298Sobrien S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit. */ 42533965Sjdp } 42633965Sjdp } 42733965Sjdp else 42833965Sjdp { 42960484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \ 43060484Sobrien && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT)) 43160484Sobrien static const char *od_buf = ""; 43233965Sjdp#else 43360484Sobrien char od_buf[100]; 43460484Sobrien od_buf[0] = '\0'; 43560484Sobrien#ifdef BFD_ASSEMBLER 43660484Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 43760484Sobrien#endif 43860484Sobrien sprintf(od_buf, "%d.%d.", 43960484Sobrien S_GET_OTHER (symbolP), 44060484Sobrien S_GET_DESC (symbolP)); 44160484Sobrien#endif 44277298Sobrien as_bad (_("Symbol \"%s\" is already defined as \"%s\"/%s%ld."), 44333965Sjdp sym_name, 44433965Sjdp segment_name (S_GET_SEGMENT (symbolP)), 44560484Sobrien od_buf, 44633965Sjdp (long) S_GET_VALUE (symbolP)); 44733965Sjdp } 44877298Sobrien } /* if the undefined symbol has no value */ 44933965Sjdp } 45033965Sjdp else 45133965Sjdp { 45277298Sobrien /* Don't blow up if the definition is the same. */ 45333965Sjdp if (!(frag_now == symbolP->sy_frag 45433965Sjdp && S_GET_VALUE (symbolP) == frag_now_fix () 45533965Sjdp && S_GET_SEGMENT (symbolP) == now_seg)) 45677298Sobrien as_bad (_("Symbol %s already defined."), sym_name); 45777298Sobrien } 45833965Sjdp 45933965Sjdp } 46060484Sobrien#ifdef BFD_ASSEMBLER 46160484Sobrien else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name)) 46260484Sobrien { 46360484Sobrien symbolP = (symbolS *) local_symbol_make (sym_name, now_seg, 46460484Sobrien (valueT) frag_now_fix (), 46560484Sobrien frag_now); 46660484Sobrien } 46760484Sobrien#endif /* BFD_ASSEMBLER */ 46833965Sjdp else 46933965Sjdp { 47033965Sjdp symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (), 47133965Sjdp frag_now); 47233965Sjdp#ifdef OBJ_VMS 47333965Sjdp S_SET_OTHER (symbolP, const_flag); 47433965Sjdp#endif /* OBJ_VMS */ 47533965Sjdp 47633965Sjdp symbol_table_insert (symbolP); 47777298Sobrien } 47833965Sjdp 47933965Sjdp if (mri_common_symbol != NULL) 48033965Sjdp { 48133965Sjdp /* This symbol is actually being defined within an MRI common 48233965Sjdp section. This requires special handling. */ 48360484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 48460484Sobrien symbolP = local_symbol_convert ((struct local_symbol *) symbolP); 48533965Sjdp symbolP->sy_value.X_op = O_symbol; 48633965Sjdp symbolP->sy_value.X_add_symbol = mri_common_symbol; 48733965Sjdp symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol); 48833965Sjdp symbolP->sy_frag = &zero_address_frag; 48933965Sjdp S_SET_SEGMENT (symbolP, expr_section); 49033965Sjdp symbolP->sy_mri_common = 1; 49133965Sjdp } 49233965Sjdp 49333965Sjdp#ifdef tc_frob_label 49433965Sjdp tc_frob_label (symbolP); 49533965Sjdp#endif 49633965Sjdp#ifdef obj_frob_label 49733965Sjdp obj_frob_label (symbolP); 49833965Sjdp#endif 49933965Sjdp 50033965Sjdp return symbolP; 50133965Sjdp} 50233965Sjdp 50377298Sobrien/* Die if we can't insert the symbol. */ 50433965Sjdp 50577298Sobrienvoid 50633965Sjdpsymbol_table_insert (symbolP) 50733965Sjdp symbolS *symbolP; 50833965Sjdp{ 50933965Sjdp register const char *error_string; 51033965Sjdp 51133965Sjdp know (symbolP); 51233965Sjdp know (S_GET_NAME (symbolP)); 51333965Sjdp 51460484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 51560484Sobrien { 51660484Sobrien error_string = hash_jam (local_hash, S_GET_NAME (symbolP), 51760484Sobrien (PTR) symbolP); 51860484Sobrien if (error_string != NULL) 51960484Sobrien as_fatal (_("Inserting \"%s\" into symbol table failed: %s"), 52060484Sobrien S_GET_NAME (symbolP), error_string); 52160484Sobrien return; 52260484Sobrien } 52360484Sobrien 52433965Sjdp if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP))) 52533965Sjdp { 52660484Sobrien as_fatal (_("Inserting \"%s\" into symbol table failed: %s"), 52733965Sjdp S_GET_NAME (symbolP), error_string); 52877298Sobrien } /* on error */ 52977298Sobrien} 53033965Sjdp 53177298Sobrien/* If a symbol name does not exist, create it as undefined, and insert 53277298Sobrien it into the symbol table. Return a pointer to it. */ 53377298Sobrien 53433965SjdpsymbolS * 53533965Sjdpsymbol_find_or_make (name) 53633965Sjdp const char *name; 53733965Sjdp{ 53833965Sjdp register symbolS *symbolP; 53933965Sjdp 54033965Sjdp symbolP = symbol_find (name); 54133965Sjdp 54233965Sjdp if (symbolP == NULL) 54333965Sjdp { 54460484Sobrien#ifdef BFD_ASSEMBLER 54560484Sobrien if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name)) 54660484Sobrien { 54760484Sobrien symbolP = md_undefined_symbol ((char *) name); 54860484Sobrien if (symbolP != NULL) 54960484Sobrien return symbolP; 55060484Sobrien 55160484Sobrien symbolP = (symbolS *) local_symbol_make (name, undefined_section, 55260484Sobrien (valueT) 0, 55360484Sobrien &zero_address_frag); 55460484Sobrien return symbolP; 55560484Sobrien } 55660484Sobrien#endif 55760484Sobrien 55833965Sjdp symbolP = symbol_make (name); 55933965Sjdp 56033965Sjdp symbol_table_insert (symbolP); 56133965Sjdp } /* if symbol wasn't found */ 56233965Sjdp 56333965Sjdp return (symbolP); 56477298Sobrien} 56533965Sjdp 56633965SjdpsymbolS * 56733965Sjdpsymbol_make (name) 56833965Sjdp CONST char *name; 56933965Sjdp{ 57033965Sjdp symbolS *symbolP; 57133965Sjdp 57277298Sobrien /* Let the machine description default it, e.g. for register names. */ 57333965Sjdp symbolP = md_undefined_symbol ((char *) name); 57433965Sjdp 57533965Sjdp if (!symbolP) 57633965Sjdp symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag); 57733965Sjdp 57833965Sjdp return (symbolP); 57977298Sobrien} 58033965Sjdp 58177298Sobrien/* Implement symbol table lookup. 58277298Sobrien In: A symbol's name as a string: '\0' can't be part of a symbol name. 58377298Sobrien Out: NULL if the name was not in the symbol table, else the address 58477298Sobrien of a struct symbol associated with that name. */ 58533965Sjdp 58633965SjdpsymbolS * 58733965Sjdpsymbol_find (name) 58833965Sjdp CONST char *name; 58933965Sjdp{ 59033965Sjdp#ifdef STRIP_UNDERSCORE 59133965Sjdp return (symbol_find_base (name, 1)); 59233965Sjdp#else /* STRIP_UNDERSCORE */ 59333965Sjdp return (symbol_find_base (name, 0)); 59433965Sjdp#endif /* STRIP_UNDERSCORE */ 59577298Sobrien} 59633965Sjdp 59733965SjdpsymbolS * 59833965Sjdpsymbol_find_base (name, strip_underscore) 59933965Sjdp CONST char *name; 60033965Sjdp int strip_underscore; 60133965Sjdp{ 60233965Sjdp if (strip_underscore && *name == '_') 60333965Sjdp name++; 60433965Sjdp 60533965Sjdp#ifdef tc_canonicalize_symbol_name 60633965Sjdp { 60733965Sjdp char *copy; 60860484Sobrien size_t len = strlen (name) + 1; 60933965Sjdp 61060484Sobrien copy = (char *) alloca (len); 61160484Sobrien memcpy (copy, name, len); 61233965Sjdp name = tc_canonicalize_symbol_name (copy); 61333965Sjdp } 61433965Sjdp#endif 61533965Sjdp 61633965Sjdp if (! symbols_case_sensitive) 61733965Sjdp { 61860484Sobrien char *copy; 61960484Sobrien const char *orig; 62060484Sobrien unsigned char c; 62133965Sjdp 62260484Sobrien orig = name; 62360484Sobrien name = copy = (char *) alloca (strlen (name) + 1); 62460484Sobrien 62560484Sobrien while ((c = *orig++) != '\0') 62660484Sobrien { 62760484Sobrien if (islower (c)) 62860484Sobrien c = toupper (c); 62960484Sobrien *copy++ = c; 63060484Sobrien } 63160484Sobrien *copy = '\0'; 63233965Sjdp } 63333965Sjdp 63460484Sobrien#ifdef BFD_ASSEMBLER 63560484Sobrien { 63660484Sobrien struct local_symbol *locsym; 63760484Sobrien 63860484Sobrien locsym = (struct local_symbol *) hash_find (local_hash, name); 63960484Sobrien if (locsym != NULL) 64060484Sobrien return (symbolS *) locsym; 64160484Sobrien } 64260484Sobrien#endif 64360484Sobrien 64433965Sjdp return ((symbolS *) hash_find (sy_hash, name)); 64533965Sjdp} 64633965Sjdp 64777298Sobrien/* Once upon a time, symbols were kept in a singly linked list. At 64877298Sobrien least coff needs to be able to rearrange them from time to time, for 64977298Sobrien which a doubly linked list is much more convenient. Loic did these 65077298Sobrien as macros which seemed dangerous to me so they're now functions. 65177298Sobrien xoxorich. */ 65233965Sjdp 65377298Sobrien/* Link symbol ADDME after symbol TARGET in the chain. */ 65477298Sobrien 65577298Sobrienvoid 65633965Sjdpsymbol_append (addme, target, rootPP, lastPP) 65733965Sjdp symbolS *addme; 65833965Sjdp symbolS *target; 65933965Sjdp symbolS **rootPP; 66033965Sjdp symbolS **lastPP; 66133965Sjdp{ 66260484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 66360484Sobrien abort (); 66460484Sobrien if (target != NULL && LOCAL_SYMBOL_CHECK (target)) 66560484Sobrien abort (); 66660484Sobrien 66733965Sjdp if (target == NULL) 66833965Sjdp { 66933965Sjdp know (*rootPP == NULL); 67033965Sjdp know (*lastPP == NULL); 67133965Sjdp addme->sy_next = NULL; 67233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 67333965Sjdp addme->sy_previous = NULL; 67433965Sjdp#endif 67533965Sjdp *rootPP = addme; 67633965Sjdp *lastPP = addme; 67733965Sjdp return; 67877298Sobrien } /* if the list is empty */ 67933965Sjdp 68033965Sjdp if (target->sy_next != NULL) 68133965Sjdp { 68233965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 68333965Sjdp target->sy_next->sy_previous = addme; 68433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 68533965Sjdp } 68633965Sjdp else 68733965Sjdp { 68833965Sjdp know (*lastPP == target); 68933965Sjdp *lastPP = addme; 69077298Sobrien } /* if we have a next */ 69133965Sjdp 69233965Sjdp addme->sy_next = target->sy_next; 69333965Sjdp target->sy_next = addme; 69433965Sjdp 69533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 69633965Sjdp addme->sy_previous = target; 69733965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 69833965Sjdp 69933965Sjdp debug_verify_symchain (symbol_rootP, symbol_lastP); 70033965Sjdp} 70133965Sjdp 70277298Sobrien/* Set the chain pointers of SYMBOL to null. */ 70377298Sobrien 70477298Sobrienvoid 70533965Sjdpsymbol_clear_list_pointers (symbolP) 70633965Sjdp symbolS *symbolP; 70733965Sjdp{ 70860484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 70960484Sobrien abort (); 71033965Sjdp symbolP->sy_next = NULL; 71133965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 71233965Sjdp symbolP->sy_previous = NULL; 71333965Sjdp#endif 71433965Sjdp} 71533965Sjdp 71633965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 71777298Sobrien/* Remove SYMBOLP from the list. */ 71877298Sobrien 71977298Sobrienvoid 72033965Sjdpsymbol_remove (symbolP, rootPP, lastPP) 72133965Sjdp symbolS *symbolP; 72233965Sjdp symbolS **rootPP; 72333965Sjdp symbolS **lastPP; 72433965Sjdp{ 72560484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 72660484Sobrien abort (); 72760484Sobrien 72833965Sjdp if (symbolP == *rootPP) 72933965Sjdp { 73033965Sjdp *rootPP = symbolP->sy_next; 73177298Sobrien } /* if it was the root */ 73233965Sjdp 73333965Sjdp if (symbolP == *lastPP) 73433965Sjdp { 73533965Sjdp *lastPP = symbolP->sy_previous; 73677298Sobrien } /* if it was the tail */ 73733965Sjdp 73833965Sjdp if (symbolP->sy_next != NULL) 73933965Sjdp { 74033965Sjdp symbolP->sy_next->sy_previous = symbolP->sy_previous; 74177298Sobrien } /* if not last */ 74233965Sjdp 74333965Sjdp if (symbolP->sy_previous != NULL) 74433965Sjdp { 74533965Sjdp symbolP->sy_previous->sy_next = symbolP->sy_next; 74677298Sobrien } /* if not first */ 74733965Sjdp 74833965Sjdp debug_verify_symchain (*rootPP, *lastPP); 74933965Sjdp} 75033965Sjdp 75177298Sobrien/* Link symbol ADDME before symbol TARGET in the chain. */ 75277298Sobrien 75377298Sobrienvoid 75433965Sjdpsymbol_insert (addme, target, rootPP, lastPP) 75533965Sjdp symbolS *addme; 75633965Sjdp symbolS *target; 75733965Sjdp symbolS **rootPP; 75860484Sobrien symbolS **lastPP ATTRIBUTE_UNUSED; 75933965Sjdp{ 76060484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 76160484Sobrien abort (); 76260484Sobrien if (LOCAL_SYMBOL_CHECK (target)) 76360484Sobrien abort (); 76460484Sobrien 76533965Sjdp if (target->sy_previous != NULL) 76633965Sjdp { 76733965Sjdp target->sy_previous->sy_next = addme; 76833965Sjdp } 76933965Sjdp else 77033965Sjdp { 77133965Sjdp know (*rootPP == target); 77233965Sjdp *rootPP = addme; 77377298Sobrien } /* if not first */ 77433965Sjdp 77533965Sjdp addme->sy_previous = target->sy_previous; 77633965Sjdp target->sy_previous = addme; 77733965Sjdp addme->sy_next = target; 77833965Sjdp 77933965Sjdp debug_verify_symchain (*rootPP, *lastPP); 78033965Sjdp} 78133965Sjdp 78233965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 78333965Sjdp 78477298Sobrienvoid 78533965Sjdpverify_symbol_chain (rootP, lastP) 78633965Sjdp symbolS *rootP; 78733965Sjdp symbolS *lastP; 78833965Sjdp{ 78933965Sjdp symbolS *symbolP = rootP; 79033965Sjdp 79133965Sjdp if (symbolP == NULL) 79233965Sjdp return; 79333965Sjdp 79433965Sjdp for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) 79533965Sjdp { 79660484Sobrien#ifdef BFD_ASSEMBLER 79760484Sobrien assert (symbolP->bsym != NULL); 79860484Sobrien#endif 79933965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 80033965Sjdp assert (symbolP->sy_next->sy_previous == symbolP); 80133965Sjdp#else 80233965Sjdp /* Walk the list anyways, to make sure pointers are still good. */ 80333965Sjdp ; 80433965Sjdp#endif /* SYMBOLS_NEED_BACKPOINTERS */ 80533965Sjdp } 80633965Sjdp 80733965Sjdp assert (lastP == symbolP); 80833965Sjdp} 80933965Sjdp 81033965Sjdpvoid 81133965Sjdpverify_symbol_chain_2 (sym) 81233965Sjdp symbolS *sym; 81333965Sjdp{ 81433965Sjdp symbolS *p = sym, *n = sym; 81533965Sjdp#ifdef SYMBOLS_NEED_BACKPOINTERS 81633965Sjdp while (symbol_previous (p)) 81733965Sjdp p = symbol_previous (p); 81833965Sjdp#endif 81933965Sjdp while (symbol_next (n)) 82033965Sjdp n = symbol_next (n); 82133965Sjdp verify_symbol_chain (p, n); 82233965Sjdp} 82333965Sjdp 82433965Sjdp/* Resolve the value of a symbol. This is called during the final 82533965Sjdp pass over the symbol table to resolve any symbols with complex 82633965Sjdp values. */ 82733965Sjdp 82838889SjdpvalueT 82938889Sjdpresolve_symbol_value (symp, finalize) 83033965Sjdp symbolS *symp; 83138889Sjdp int finalize; 83233965Sjdp{ 83333965Sjdp int resolved; 83438889Sjdp valueT final_val; 83538889Sjdp segT final_seg; 83633965Sjdp 83760484Sobrien#ifdef BFD_ASSEMBLER 83860484Sobrien if (LOCAL_SYMBOL_CHECK (symp)) 83960484Sobrien { 84060484Sobrien struct local_symbol *locsym = (struct local_symbol *) symp; 84160484Sobrien 84260484Sobrien if (local_symbol_resolved_p (locsym)) 84377298Sobrien return locsym->lsy_offset / bfd_octets_per_byte (stdoutput); 84460484Sobrien 84560484Sobrien final_val = (local_symbol_get_frag (locsym)->fr_address 84677298Sobrien + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput); 84760484Sobrien 84860484Sobrien if (finalize) 84960484Sobrien { 85060484Sobrien locsym->lsy_offset = final_val; 85160484Sobrien local_symbol_mark_resolved (locsym); 85260484Sobrien } 85360484Sobrien 85460484Sobrien return final_val; 85560484Sobrien } 85660484Sobrien#endif 85760484Sobrien 85833965Sjdp if (symp->sy_resolved) 85938889Sjdp { 86038889Sjdp if (symp->sy_value.X_op == O_constant) 86138889Sjdp return (valueT) symp->sy_value.X_add_number; 86238889Sjdp else 86338889Sjdp return 0; 86438889Sjdp } 86533965Sjdp 86633965Sjdp resolved = 0; 86738889Sjdp final_seg = S_GET_SEGMENT (symp); 86833965Sjdp 86933965Sjdp if (symp->sy_resolving) 87033965Sjdp { 87138889Sjdp if (finalize) 87277298Sobrien as_bad (_("Symbol definition loop encountered at %s"), 87377298Sobrien S_GET_NAME (symp)); 87438889Sjdp final_val = 0; 87533965Sjdp resolved = 1; 87633965Sjdp } 87733965Sjdp else 87833965Sjdp { 87938889Sjdp symbolS *add_symbol, *op_symbol; 88038889Sjdp offsetT left, right; 88133965Sjdp segT seg_left, seg_right; 88238889Sjdp operatorT op; 88333965Sjdp 88433965Sjdp symp->sy_resolving = 1; 88533965Sjdp 88638889Sjdp /* Help out with CSE. */ 88738889Sjdp add_symbol = symp->sy_value.X_add_symbol; 88838889Sjdp op_symbol = symp->sy_value.X_op_symbol; 88938889Sjdp final_val = symp->sy_value.X_add_number; 89038889Sjdp op = symp->sy_value.X_op; 89138889Sjdp 89238889Sjdp switch (op) 89333965Sjdp { 89438889Sjdp default: 89538889Sjdp BAD_CASE (op); 89638889Sjdp break; 89733965Sjdp 89833965Sjdp case O_absent: 89938889Sjdp final_val = 0; 90033965Sjdp /* Fall through. */ 90138889Sjdp 90233965Sjdp case O_constant: 90360484Sobrien final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; 90438889Sjdp if (final_seg == expr_section) 90538889Sjdp final_seg = absolute_section; 90633965Sjdp resolved = 1; 90733965Sjdp break; 90833965Sjdp 90933965Sjdp case O_symbol: 91038889Sjdp case O_symbol_rva: 91138889Sjdp left = resolve_symbol_value (add_symbol, finalize); 91238889Sjdp do_symbol: 91333965Sjdp 91433965Sjdp if (symp->sy_mri_common) 91533965Sjdp { 91633965Sjdp /* This is a symbol inside an MRI common section. The 91733965Sjdp relocation routines are going to handle it specially. 91833965Sjdp Don't change the value. */ 91960484Sobrien resolved = symbol_resolved_p (add_symbol); 92033965Sjdp break; 92133965Sjdp } 92233965Sjdp 92338889Sjdp if (finalize && final_val == 0) 92460484Sobrien { 92560484Sobrien if (LOCAL_SYMBOL_CHECK (add_symbol)) 92660484Sobrien add_symbol = local_symbol_convert ((struct local_symbol *) 92760484Sobrien add_symbol); 92860484Sobrien copy_symbol_attributes (symp, add_symbol); 92960484Sobrien } 93033965Sjdp 93133965Sjdp /* If we have equated this symbol to an undefined symbol, we 93233965Sjdp keep X_op set to O_symbol, and we don't change 93333965Sjdp X_add_number. This permits the routine which writes out 93433965Sjdp relocation to detect this case, and convert the 93533965Sjdp relocation to be against the symbol to which this symbol 93633965Sjdp is equated. */ 93738889Sjdp if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol)) 93833965Sjdp { 93938889Sjdp if (finalize) 94038889Sjdp { 94160484Sobrien S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol)); 94238889Sjdp symp->sy_value.X_op = O_symbol; 94360484Sobrien symp->sy_value.X_add_symbol = add_symbol; 94438889Sjdp symp->sy_value.X_add_number = final_val; 94538889Sjdp } 94638889Sjdp final_val = 0; 94760484Sobrien resolved = symbol_resolved_p (add_symbol); 94838889Sjdp goto exit_dont_set_value; 94933965Sjdp } 95033965Sjdp else 95133965Sjdp { 95238889Sjdp final_val += symp->sy_frag->fr_address + left; 95338889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 95438889Sjdp final_seg = S_GET_SEGMENT (add_symbol); 95533965Sjdp } 95633965Sjdp 95760484Sobrien resolved = symbol_resolved_p (add_symbol); 95833965Sjdp break; 95933965Sjdp 96033965Sjdp case O_uminus: 96133965Sjdp case O_bit_not: 96233965Sjdp case O_logical_not: 96338889Sjdp left = resolve_symbol_value (add_symbol, finalize); 96438889Sjdp 96538889Sjdp if (op == O_uminus) 96638889Sjdp left = -left; 96738889Sjdp else if (op == O_logical_not) 96838889Sjdp left = !left; 96933965Sjdp else 97038889Sjdp left = ~left; 97138889Sjdp 97238889Sjdp final_val += left + symp->sy_frag->fr_address; 97338889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 97438889Sjdp final_seg = absolute_section; 97538889Sjdp 97660484Sobrien resolved = symbol_resolved_p (add_symbol); 97733965Sjdp break; 97833965Sjdp 97933965Sjdp case O_multiply: 98033965Sjdp case O_divide: 98133965Sjdp case O_modulus: 98233965Sjdp case O_left_shift: 98333965Sjdp case O_right_shift: 98433965Sjdp case O_bit_inclusive_or: 98533965Sjdp case O_bit_or_not: 98633965Sjdp case O_bit_exclusive_or: 98733965Sjdp case O_bit_and: 98833965Sjdp case O_add: 98933965Sjdp case O_subtract: 99033965Sjdp case O_eq: 99133965Sjdp case O_ne: 99233965Sjdp case O_lt: 99333965Sjdp case O_le: 99433965Sjdp case O_ge: 99533965Sjdp case O_gt: 99633965Sjdp case O_logical_and: 99733965Sjdp case O_logical_or: 99838889Sjdp left = resolve_symbol_value (add_symbol, finalize); 99938889Sjdp right = resolve_symbol_value (op_symbol, finalize); 100038889Sjdp seg_left = S_GET_SEGMENT (add_symbol); 100138889Sjdp seg_right = S_GET_SEGMENT (op_symbol); 100233965Sjdp 100338889Sjdp /* Simplify addition or subtraction of a constant by folding the 100438889Sjdp constant into X_add_number. */ 100538889Sjdp if (op == O_add || op == O_subtract) 100638889Sjdp { 100738889Sjdp if (seg_right == absolute_section) 100838889Sjdp { 100938889Sjdp if (op == O_add) 101038889Sjdp final_val += right; 101138889Sjdp else 101238889Sjdp final_val -= right; 101338889Sjdp op = O_symbol; 101438889Sjdp op_symbol = NULL; 101538889Sjdp goto do_symbol; 101638889Sjdp } 101738889Sjdp else if (seg_left == absolute_section && op == O_add) 101838889Sjdp { 101938889Sjdp op = O_symbol; 102038889Sjdp final_val += left; 102138889Sjdp add_symbol = op_symbol; 102238889Sjdp left = right; 102338889Sjdp op_symbol = NULL; 102438889Sjdp goto do_symbol; 102538889Sjdp } 102638889Sjdp } 102738889Sjdp 102833965Sjdp /* Subtraction is permitted if both operands are in the same 102933965Sjdp section. Otherwise, both operands must be absolute. We 103033965Sjdp already handled the case of addition or subtraction of a 103133965Sjdp constant above. This will probably need to be changed 103233965Sjdp for an object file format which supports arbitrary 103333965Sjdp expressions, such as IEEE-695. */ 103438889Sjdp /* Don't emit messages unless we're finalizing the symbol value, 103538889Sjdp otherwise we may get the same message multiple times. */ 103660484Sobrien if ((seg_left != absolute_section 103760484Sobrien || seg_right != absolute_section) 103860484Sobrien && (op != O_subtract 103960484Sobrien || seg_left != seg_right 104060484Sobrien || seg_left == undefined_section) 104138889Sjdp && finalize) 104233965Sjdp { 104333965Sjdp char *file; 104433965Sjdp unsigned int line; 104533965Sjdp 104633965Sjdp if (expr_symbol_where (symp, &file, &line)) 104733965Sjdp { 104833965Sjdp if (seg_left == undefined_section) 104933965Sjdp as_bad_where (file, line, 105060484Sobrien _("undefined symbol %s in operation"), 105133965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol)); 105233965Sjdp if (seg_right == undefined_section) 105333965Sjdp as_bad_where (file, line, 105460484Sobrien _("undefined symbol %s in operation"), 105533965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol)); 105633965Sjdp if (seg_left != undefined_section 105733965Sjdp && seg_right != undefined_section) 105877298Sobrien as_bad_where (file, line, 105977298Sobrien _("invalid section for operation")); 106033965Sjdp } 106133965Sjdp else 106233965Sjdp { 106333965Sjdp if (seg_left == undefined_section) 106460484Sobrien as_bad (_("undefined symbol %s in operation setting %s"), 106533965Sjdp S_GET_NAME (symp->sy_value.X_add_symbol), 106633965Sjdp S_GET_NAME (symp)); 106733965Sjdp if (seg_right == undefined_section) 106860484Sobrien as_bad (_("undefined symbol %s in operation setting %s"), 106933965Sjdp S_GET_NAME (symp->sy_value.X_op_symbol), 107033965Sjdp S_GET_NAME (symp)); 107133965Sjdp if (seg_left != undefined_section 107233965Sjdp && seg_right != undefined_section) 107360484Sobrien as_bad (_("invalid section for operation setting %s"), 107433965Sjdp S_GET_NAME (symp)); 107533965Sjdp } 107633965Sjdp } 107733965Sjdp 107838889Sjdp /* Check for division by zero. */ 107938889Sjdp if ((op == O_divide || op == O_modulus) && right == 0) 108038889Sjdp { 108138889Sjdp /* If seg_right is not absolute_section, then we've 108238889Sjdp already issued a warning about using a bad symbol. */ 108338889Sjdp if (seg_right == absolute_section && finalize) 108438889Sjdp { 108538889Sjdp char *file; 108638889Sjdp unsigned int line; 108738889Sjdp 108838889Sjdp if (expr_symbol_where (symp, &file, &line)) 108960484Sobrien as_bad_where (file, line, _("division by zero")); 109038889Sjdp else 109160484Sobrien as_bad (_("division by zero when setting %s"), 109238889Sjdp S_GET_NAME (symp)); 109338889Sjdp } 109438889Sjdp 109538889Sjdp right = 1; 109638889Sjdp } 109738889Sjdp 109833965Sjdp switch (symp->sy_value.X_op) 109933965Sjdp { 110038889Sjdp case O_multiply: left *= right; break; 110138889Sjdp case O_divide: left /= right; break; 110238889Sjdp case O_modulus: left %= right; break; 110338889Sjdp case O_left_shift: left <<= right; break; 110438889Sjdp case O_right_shift: left >>= right; break; 110538889Sjdp case O_bit_inclusive_or: left |= right; break; 110638889Sjdp case O_bit_or_not: left |= ~right; break; 110738889Sjdp case O_bit_exclusive_or: left ^= right; break; 110838889Sjdp case O_bit_and: left &= right; break; 110938889Sjdp case O_add: left += right; break; 111038889Sjdp case O_subtract: left -= right; break; 111138889Sjdp case O_eq: left = left == right ? ~ (offsetT) 0 : 0; break; 111238889Sjdp case O_ne: left = left != right ? ~ (offsetT) 0 : 0; break; 111338889Sjdp case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; 111438889Sjdp case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; 111538889Sjdp case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; 111638889Sjdp case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; 111738889Sjdp case O_logical_and: left = left && right; break; 111838889Sjdp case O_logical_or: left = left || right; break; 111938889Sjdp default: abort (); 112033965Sjdp } 112138889Sjdp 112238889Sjdp final_val += symp->sy_frag->fr_address + left; 112338889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 112438889Sjdp final_seg = absolute_section; 112560484Sobrien resolved = (symbol_resolved_p (add_symbol) 112660484Sobrien && symbol_resolved_p (op_symbol)); 112777298Sobrien break; 112833965Sjdp 112933965Sjdp case O_register: 113033965Sjdp case O_big: 113133965Sjdp case O_illegal: 113233965Sjdp /* Give an error (below) if not in expr_section. We don't 113333965Sjdp want to worry about expr_section symbols, because they 113433965Sjdp are fictional (they are created as part of expression 113533965Sjdp resolution), and any problems may not actually mean 113633965Sjdp anything. */ 113733965Sjdp break; 113833965Sjdp } 113938889Sjdp 114038889Sjdp symp->sy_resolving = 0; 114133965Sjdp } 114233965Sjdp 114338889Sjdp if (finalize) 114438889Sjdp { 114538889Sjdp S_SET_VALUE (symp, final_val); 114638889Sjdp 114738889Sjdp#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER) 114838889Sjdp /* The old a.out backend does not handle S_SET_SEGMENT correctly 114938889Sjdp for a stab symbol, so we use this bad hack. */ 115038889Sjdp if (final_seg != S_GET_SEGMENT (symp)) 115138889Sjdp#endif 115238889Sjdp S_SET_SEGMENT (symp, final_seg); 115338889Sjdp } 115438889Sjdp 115538889Sjdpexit_dont_set_value: 115633965Sjdp /* Don't worry if we can't resolve an expr_section symbol. */ 115738889Sjdp if (finalize) 115833965Sjdp { 115938889Sjdp if (resolved) 116038889Sjdp symp->sy_resolved = 1; 116138889Sjdp else if (S_GET_SEGMENT (symp) != expr_section) 116238889Sjdp { 116377298Sobrien as_bad (_("can't resolve value for symbol \"%s\""), 116477298Sobrien S_GET_NAME (symp)); 116538889Sjdp symp->sy_resolved = 1; 116638889Sjdp } 116733965Sjdp } 116838889Sjdp 116938889Sjdp return final_val; 117033965Sjdp} 117133965Sjdp 117260484Sobrien#ifdef BFD_ASSEMBLER 117360484Sobrien 117460484Sobrienstatic void resolve_local_symbol PARAMS ((const char *, PTR)); 117560484Sobrien 117660484Sobrien/* A static function passed to hash_traverse. */ 117760484Sobrien 117860484Sobrienstatic void 117960484Sobrienresolve_local_symbol (key, value) 118060484Sobrien const char *key ATTRIBUTE_UNUSED; 118160484Sobrien PTR value; 118260484Sobrien{ 118360484Sobrien if (value != NULL) 118460484Sobrien resolve_symbol_value (value, 1); 118560484Sobrien} 118660484Sobrien 118760484Sobrien#endif 118860484Sobrien 118960484Sobrien/* Resolve all local symbols. */ 119060484Sobrien 119160484Sobrienvoid 119260484Sobrienresolve_local_symbol_values () 119360484Sobrien{ 119460484Sobrien#ifdef BFD_ASSEMBLER 119560484Sobrien hash_traverse (local_hash, resolve_local_symbol); 119660484Sobrien#endif 119760484Sobrien} 119860484Sobrien 119933965Sjdp/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". 120033965Sjdp They are *really* local. That is, they go out of scope whenever we see a 120133965Sjdp label that isn't local. Also, like fb labels, there can be multiple 120233965Sjdp instances of a dollar label. Therefor, we name encode each instance with 120333965Sjdp the instance number, keep a list of defined symbols separate from the real 120433965Sjdp symbol table, and we treat these buggers as a sparse array. */ 120533965Sjdp 120633965Sjdpstatic long *dollar_labels; 120733965Sjdpstatic long *dollar_label_instances; 120833965Sjdpstatic char *dollar_label_defines; 120938889Sjdpstatic unsigned long dollar_label_count; 121033965Sjdpstatic unsigned long dollar_label_max; 121133965Sjdp 121277298Sobrienint 121333965Sjdpdollar_label_defined (label) 121433965Sjdp long label; 121533965Sjdp{ 121633965Sjdp long *i; 121733965Sjdp 121833965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 121933965Sjdp 122033965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 122133965Sjdp if (*i == label) 122233965Sjdp return dollar_label_defines[i - dollar_labels]; 122333965Sjdp 122477298Sobrien /* If we get here, label isn't defined. */ 122533965Sjdp return 0; 122677298Sobrien} 122733965Sjdp 122833965Sjdpstatic long 122933965Sjdpdollar_label_instance (label) 123033965Sjdp long label; 123133965Sjdp{ 123233965Sjdp long *i; 123333965Sjdp 123433965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 123533965Sjdp 123633965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 123733965Sjdp if (*i == label) 123833965Sjdp return (dollar_label_instances[i - dollar_labels]); 123933965Sjdp 124077298Sobrien /* If we get here, we haven't seen the label before. 124177298Sobrien Therefore its instance count is zero. */ 124233965Sjdp return 0; 124333965Sjdp} 124433965Sjdp 124577298Sobrienvoid 124633965Sjdpdollar_label_clear () 124733965Sjdp{ 124833965Sjdp memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count); 124933965Sjdp} 125033965Sjdp 125133965Sjdp#define DOLLAR_LABEL_BUMP_BY 10 125233965Sjdp 125377298Sobrienvoid 125433965Sjdpdefine_dollar_label (label) 125533965Sjdp long label; 125633965Sjdp{ 125733965Sjdp long *i; 125833965Sjdp 125933965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 126033965Sjdp if (*i == label) 126133965Sjdp { 126233965Sjdp ++dollar_label_instances[i - dollar_labels]; 126333965Sjdp dollar_label_defines[i - dollar_labels] = 1; 126433965Sjdp return; 126533965Sjdp } 126633965Sjdp 126777298Sobrien /* If we get to here, we don't have label listed yet. */ 126833965Sjdp 126933965Sjdp if (dollar_labels == NULL) 127033965Sjdp { 127133965Sjdp dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 127233965Sjdp dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 127333965Sjdp dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY); 127433965Sjdp dollar_label_max = DOLLAR_LABEL_BUMP_BY; 127533965Sjdp dollar_label_count = 0; 127633965Sjdp } 127733965Sjdp else if (dollar_label_count == dollar_label_max) 127833965Sjdp { 127933965Sjdp dollar_label_max += DOLLAR_LABEL_BUMP_BY; 128033965Sjdp dollar_labels = (long *) xrealloc ((char *) dollar_labels, 128133965Sjdp dollar_label_max * sizeof (long)); 128233965Sjdp dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances, 128333965Sjdp dollar_label_max * sizeof (long)); 128433965Sjdp dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max); 128577298Sobrien } /* if we needed to grow */ 128633965Sjdp 128733965Sjdp dollar_labels[dollar_label_count] = label; 128833965Sjdp dollar_label_instances[dollar_label_count] = 1; 128933965Sjdp dollar_label_defines[dollar_label_count] = 1; 129033965Sjdp ++dollar_label_count; 129133965Sjdp} 129233965Sjdp 129377298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 129433965Sjdp 129577298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Am" 129677298Sobrien where n is the label number and m is the instance number. "L" makes 129777298Sobrien it a label discarded unless debugging and "^A"('\1') ensures no 129877298Sobrien ordinary symbol SHOULD get the same name as a local label 129977298Sobrien symbol. The first "4:" is "L4^A1" - the m numbers begin at 1. 130077298Sobrien 130177298Sobrien fb labels get the same treatment, except that ^B is used in place 130277298Sobrien of ^A. */ 130377298Sobrien 130477298Sobrienchar * /* Return local label name. */ 130533965Sjdpdollar_label_name (n, augend) 130677298Sobrien register long n; /* we just saw "n$:" : n a number. */ 130777298Sobrien register int augend; /* 0 for current instance, 1 for new instance. */ 130833965Sjdp{ 130933965Sjdp long i; 131077298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 131133965Sjdp static char symbol_name_build[24]; 131233965Sjdp register char *p; 131333965Sjdp register char *q; 131477298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 131533965Sjdp 131633965Sjdp know (n >= 0); 131733965Sjdp know (augend == 0 || augend == 1); 131833965Sjdp p = symbol_name_build; 131960484Sobrien#ifdef LOCAL_LABEL_PREFIX 132060484Sobrien *p++ = LOCAL_LABEL_PREFIX; 132160484Sobrien#endif 132233965Sjdp *p++ = 'L'; 132333965Sjdp 132477298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 132577298Sobrien /* Label number. */ 132633965Sjdp q = symbol_name_temporary; 132733965Sjdp for (*q++ = 0, i = n; i; ++q) 132833965Sjdp { 132933965Sjdp *q = i % 10 + '0'; 133033965Sjdp i /= 10; 133133965Sjdp } 133233965Sjdp while ((*p = *--q) != '\0') 133333965Sjdp ++p; 133433965Sjdp 133577298Sobrien *p++ = DOLLAR_LABEL_CHAR; /* ^A */ 133633965Sjdp 133777298Sobrien /* Instance number. */ 133833965Sjdp q = symbol_name_temporary; 133933965Sjdp for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q) 134033965Sjdp { 134133965Sjdp *q = i % 10 + '0'; 134233965Sjdp i /= 10; 134333965Sjdp } 134433965Sjdp while ((*p++ = *--q) != '\0');; 134533965Sjdp 134677298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 134733965Sjdp return symbol_name_build; 134833965Sjdp} 134933965Sjdp 135077298Sobrien/* Sombody else's idea of local labels. They are made by "n:" where n 135177298Sobrien is any decimal digit. Refer to them with 135277298Sobrien "nb" for previous (backward) n: 135377298Sobrien or "nf" for next (forward) n:. 135433965Sjdp 135577298Sobrien We do a little better and let n be any number, not just a single digit, but 135677298Sobrien since the other guy's assembler only does ten, we treat the first ten 135777298Sobrien specially. 135877298Sobrien 135977298Sobrien Like someone else's assembler, we have one set of local label counters for 136077298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 136177298Sobrien implies that one can refer to a label in another segment, and indeed some 136277298Sobrien crufty compilers have done just that. 136377298Sobrien 136477298Sobrien Since there could be a LOT of these things, treat them as a sparse 136577298Sobrien array. */ 136677298Sobrien 136733965Sjdp#define FB_LABEL_SPECIAL (10) 136833965Sjdp 136933965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 137033965Sjdpstatic long *fb_labels; 137133965Sjdpstatic long *fb_label_instances; 137233965Sjdpstatic long fb_label_count; 137333965Sjdpstatic long fb_label_max; 137433965Sjdp 137577298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 137633965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 137733965Sjdp 137877298Sobrienstatic void 137933965Sjdpfb_label_init () 138033965Sjdp{ 138133965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 138277298Sobrien} 138333965Sjdp 138477298Sobrien/* Add one to the instance number of this fb label. */ 138577298Sobrien 138677298Sobrienvoid 138733965Sjdpfb_label_instance_inc (label) 138833965Sjdp long label; 138933965Sjdp{ 139033965Sjdp long *i; 139133965Sjdp 139233965Sjdp if (label < FB_LABEL_SPECIAL) 139333965Sjdp { 139433965Sjdp ++fb_low_counter[label]; 139533965Sjdp return; 139633965Sjdp } 139733965Sjdp 139833965Sjdp if (fb_labels != NULL) 139933965Sjdp { 140033965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 140133965Sjdp i < fb_labels + fb_label_count; ++i) 140233965Sjdp { 140333965Sjdp if (*i == label) 140433965Sjdp { 140533965Sjdp ++fb_label_instances[i - fb_labels]; 140633965Sjdp return; 140777298Sobrien } /* if we find it */ 140877298Sobrien } /* for each existing label */ 140933965Sjdp } 141033965Sjdp 141177298Sobrien /* If we get to here, we don't have label listed yet. */ 141233965Sjdp 141333965Sjdp if (fb_labels == NULL) 141433965Sjdp { 141533965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 141633965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 141733965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 141833965Sjdp fb_label_count = FB_LABEL_SPECIAL; 141933965Sjdp 142033965Sjdp } 142133965Sjdp else if (fb_label_count == fb_label_max) 142233965Sjdp { 142333965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 142433965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 142533965Sjdp fb_label_max * sizeof (long)); 142633965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 142733965Sjdp fb_label_max * sizeof (long)); 142877298Sobrien } /* if we needed to grow */ 142933965Sjdp 143033965Sjdp fb_labels[fb_label_count] = label; 143133965Sjdp fb_label_instances[fb_label_count] = 1; 143233965Sjdp ++fb_label_count; 143333965Sjdp} 143433965Sjdp 143577298Sobrienstatic long 143633965Sjdpfb_label_instance (label) 143733965Sjdp long label; 143833965Sjdp{ 143933965Sjdp long *i; 144033965Sjdp 144133965Sjdp if (label < FB_LABEL_SPECIAL) 144233965Sjdp { 144333965Sjdp return (fb_low_counter[label]); 144433965Sjdp } 144533965Sjdp 144633965Sjdp if (fb_labels != NULL) 144733965Sjdp { 144833965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 144933965Sjdp i < fb_labels + fb_label_count; ++i) 145033965Sjdp { 145133965Sjdp if (*i == label) 145233965Sjdp { 145333965Sjdp return (fb_label_instances[i - fb_labels]); 145477298Sobrien } /* if we find it */ 145577298Sobrien } /* for each existing label */ 145633965Sjdp } 145733965Sjdp 145833965Sjdp /* We didn't find the label, so this must be a reference to the 145933965Sjdp first instance. */ 146033965Sjdp return 0; 146133965Sjdp} 146233965Sjdp 146377298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 146433965Sjdp 146577298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 146677298Sobrien where n is the label number and m is the instance number. "L" makes 146777298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 146877298Sobrien ordinary symbol SHOULD get the same name as a local label 146977298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 147077298Sobrien 147177298Sobrien dollar labels get the same treatment, except that ^A is used in 147277298Sobrien place of ^B. */ 147377298Sobrien 147477298Sobrienchar * /* Return local label name. */ 147533965Sjdpfb_label_name (n, augend) 147677298Sobrien long n; /* We just saw "n:", "nf" or "nb" : n a number. */ 147777298Sobrien long augend; /* 0 for nb, 1 for n:, nf. */ 147833965Sjdp{ 147933965Sjdp long i; 148077298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 148133965Sjdp static char symbol_name_build[24]; 148233965Sjdp register char *p; 148333965Sjdp register char *q; 148477298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 148533965Sjdp 148633965Sjdp know (n >= 0); 148733965Sjdp know (augend == 0 || augend == 1); 148833965Sjdp p = symbol_name_build; 148977298Sobrien#ifdef LOCAL_LABEL_PREFIX 149077298Sobrien *p++ = LOCAL_LABEL_PREFIX; 149177298Sobrien#endif 149233965Sjdp *p++ = 'L'; 149333965Sjdp 149477298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 149577298Sobrien /* Label number. */ 149633965Sjdp q = symbol_name_temporary; 149733965Sjdp for (*q++ = 0, i = n; i; ++q) 149833965Sjdp { 149933965Sjdp *q = i % 10 + '0'; 150033965Sjdp i /= 10; 150133965Sjdp } 150233965Sjdp while ((*p = *--q) != '\0') 150333965Sjdp ++p; 150433965Sjdp 150577298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 150633965Sjdp 150777298Sobrien /* Instance number. */ 150833965Sjdp q = symbol_name_temporary; 150933965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 151033965Sjdp { 151133965Sjdp *q = i % 10 + '0'; 151233965Sjdp i /= 10; 151333965Sjdp } 151433965Sjdp while ((*p++ = *--q) != '\0');; 151533965Sjdp 151677298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 151733965Sjdp return (symbol_name_build); 151877298Sobrien} 151933965Sjdp 152077298Sobrien/* Decode name that may have been generated by foo_label_name() above. 152177298Sobrien If the name wasn't generated by foo_label_name(), then return it 152277298Sobrien unaltered. This is used for error messages. */ 152333965Sjdp 152433965Sjdpchar * 152533965Sjdpdecode_local_label_name (s) 152633965Sjdp char *s; 152733965Sjdp{ 152833965Sjdp char *p; 152933965Sjdp char *symbol_decode; 153033965Sjdp int label_number; 153133965Sjdp int instance_number; 153233965Sjdp char *type; 153360484Sobrien const char *message_format = _("\"%d\" (instance number %d of a %s label)"); 153477298Sobrien int index = 0; 153533965Sjdp 153677298Sobrien#ifdef LOCAL_LABEL_PREFIX 153777298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 153877298Sobrien ++index; 153977298Sobrien#endif 154077298Sobrien 154177298Sobrien if (s[index] != 'L') 154233965Sjdp return s; 154333965Sjdp 154477298Sobrien for (label_number = 0, p = s + index + 1; isdigit ((unsigned char) *p); ++p) 154533965Sjdp label_number = (10 * label_number) + *p - '0'; 154633965Sjdp 154777298Sobrien if (*p == DOLLAR_LABEL_CHAR) 154833965Sjdp type = "dollar"; 154977298Sobrien else if (*p == LOCAL_LABEL_CHAR) 155033965Sjdp type = "fb"; 155133965Sjdp else 155233965Sjdp return s; 155333965Sjdp 155438889Sjdp for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p) 155533965Sjdp instance_number = (10 * instance_number) + *p - '0'; 155633965Sjdp 155733965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 155833965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 155933965Sjdp 156033965Sjdp return symbol_decode; 156133965Sjdp} 156233965Sjdp 156333965Sjdp/* Get the value of a symbol. */ 156433965Sjdp 156533965SjdpvalueT 156633965SjdpS_GET_VALUE (s) 156733965Sjdp symbolS *s; 156833965Sjdp{ 156960484Sobrien#ifdef BFD_ASSEMBLER 157060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 157160484Sobrien return ((struct local_symbol *) s)->lsy_offset; 157260484Sobrien#endif 157360484Sobrien 157438889Sjdp if (!s->sy_resolved && s->sy_value.X_op != O_constant) 157538889Sjdp resolve_symbol_value (s, 1); 157633965Sjdp if (s->sy_value.X_op != O_constant) 157733965Sjdp { 157833965Sjdp static symbolS *recur; 157933965Sjdp 158033965Sjdp /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON 158133965Sjdp may call S_GET_VALUE. We use a static symbol to avoid the 158233965Sjdp immediate recursion. */ 158333965Sjdp if (recur == s) 158433965Sjdp return (valueT) s->sy_value.X_add_number; 158533965Sjdp recur = s; 158633965Sjdp if (! s->sy_resolved 158733965Sjdp || s->sy_value.X_op != O_symbol 158833965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 158960484Sobrien as_bad (_("Attempt to get value of unresolved symbol %s"), 159033965Sjdp S_GET_NAME (s)); 159133965Sjdp recur = NULL; 159233965Sjdp } 159333965Sjdp return (valueT) s->sy_value.X_add_number; 159433965Sjdp} 159533965Sjdp 159633965Sjdp/* Set the value of a symbol. */ 159733965Sjdp 159833965Sjdpvoid 159933965SjdpS_SET_VALUE (s, val) 160033965Sjdp symbolS *s; 160133965Sjdp valueT val; 160233965Sjdp{ 160360484Sobrien#ifdef BFD_ASSEMBLER 160460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 160560484Sobrien { 160660484Sobrien ((struct local_symbol *) s)->lsy_offset = val; 160760484Sobrien return; 160860484Sobrien } 160960484Sobrien#endif 161060484Sobrien 161133965Sjdp s->sy_value.X_op = O_constant; 161233965Sjdp s->sy_value.X_add_number = (offsetT) val; 161333965Sjdp s->sy_value.X_unsigned = 0; 161433965Sjdp} 161533965Sjdp 161633965Sjdpvoid 161733965Sjdpcopy_symbol_attributes (dest, src) 161833965Sjdp symbolS *dest, *src; 161933965Sjdp{ 162060484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 162160484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 162260484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 162360484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 162460484Sobrien 162533965Sjdp#ifdef BFD_ASSEMBLER 162633965Sjdp /* In an expression, transfer the settings of these flags. 162733965Sjdp The user can override later, of course. */ 162838889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 162933965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 163033965Sjdp#endif 163133965Sjdp 163233965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 163333965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 163433965Sjdp#endif 163533965Sjdp} 163633965Sjdp 163733965Sjdp#ifdef BFD_ASSEMBLER 163833965Sjdp 163933965Sjdpint 164060484SobrienS_IS_FUNCTION (s) 164160484Sobrien symbolS *s; 164260484Sobrien{ 164360484Sobrien flagword flags; 164460484Sobrien 164560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 164660484Sobrien return 0; 164760484Sobrien 164860484Sobrien flags = s->bsym->flags; 164960484Sobrien 165060484Sobrien return (flags & BSF_FUNCTION) != 0; 165160484Sobrien} 165260484Sobrien 165360484Sobrienint 165433965SjdpS_IS_EXTERNAL (s) 165533965Sjdp symbolS *s; 165633965Sjdp{ 165760484Sobrien flagword flags; 165833965Sjdp 165960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 166060484Sobrien return 0; 166160484Sobrien 166260484Sobrien flags = s->bsym->flags; 166360484Sobrien 166477298Sobrien /* Sanity check. */ 166538889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 166633965Sjdp abort (); 166733965Sjdp 166833965Sjdp return (flags & BSF_GLOBAL) != 0; 166933965Sjdp} 167033965Sjdp 167133965Sjdpint 167233965SjdpS_IS_WEAK (s) 167333965Sjdp symbolS *s; 167433965Sjdp{ 167560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 167660484Sobrien return 0; 167733965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 167833965Sjdp} 167933965Sjdp 168033965Sjdpint 168133965SjdpS_IS_COMMON (s) 168233965Sjdp symbolS *s; 168333965Sjdp{ 168460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 168560484Sobrien return 0; 168633965Sjdp return bfd_is_com_section (s->bsym->section); 168733965Sjdp} 168833965Sjdp 168933965Sjdpint 169033965SjdpS_IS_DEFINED (s) 169133965Sjdp symbolS *s; 169233965Sjdp{ 169360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 169460484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 169533965Sjdp return s->bsym->section != undefined_section; 169633965Sjdp} 169733965Sjdp 169833965Sjdpint 169933965SjdpS_IS_DEBUG (s) 170033965Sjdp symbolS *s; 170133965Sjdp{ 170260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 170360484Sobrien return 0; 170433965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 170533965Sjdp return 1; 170633965Sjdp return 0; 170733965Sjdp} 170833965Sjdp 170933965Sjdpint 171033965SjdpS_IS_LOCAL (s) 171133965Sjdp symbolS *s; 171233965Sjdp{ 171360484Sobrien flagword flags; 171433965Sjdp const char *name; 171533965Sjdp 171660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 171760484Sobrien return 1; 171860484Sobrien 171960484Sobrien flags = s->bsym->flags; 172060484Sobrien 172177298Sobrien /* Sanity check. */ 172238889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 172333965Sjdp abort (); 172433965Sjdp 172533965Sjdp if (bfd_get_section (s->bsym) == reg_section) 172633965Sjdp return 1; 172733965Sjdp 172838889Sjdp if (flag_strip_local_absolute 172938889Sjdp && (flags & BSF_GLOBAL) == 0 173038889Sjdp && bfd_get_section (s->bsym) == absolute_section) 173138889Sjdp return 1; 173238889Sjdp 173333965Sjdp name = S_GET_NAME (s); 173433965Sjdp return (name != NULL 173533965Sjdp && ! S_IS_DEBUG (s) 173677298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 173777298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 173833965Sjdp || (! flag_keep_locals 173933965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 174033965Sjdp || (flag_mri 174133965Sjdp && name[0] == '?' 174233965Sjdp && name[1] == '?'))))); 174333965Sjdp} 174433965Sjdp 174533965Sjdpint 174633965SjdpS_IS_EXTERN (s) 174733965Sjdp symbolS *s; 174833965Sjdp{ 174933965Sjdp return S_IS_EXTERNAL (s); 175033965Sjdp} 175133965Sjdp 175233965Sjdpint 175333965SjdpS_IS_STABD (s) 175433965Sjdp symbolS *s; 175533965Sjdp{ 175633965Sjdp return S_GET_NAME (s) == 0; 175733965Sjdp} 175833965Sjdp 175933965SjdpCONST char * 176033965SjdpS_GET_NAME (s) 176133965Sjdp symbolS *s; 176233965Sjdp{ 176360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 176460484Sobrien return ((struct local_symbol *) s)->lsy_name; 176533965Sjdp return s->bsym->name; 176633965Sjdp} 176733965Sjdp 176833965SjdpsegT 176933965SjdpS_GET_SEGMENT (s) 177033965Sjdp symbolS *s; 177133965Sjdp{ 177260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 177360484Sobrien return ((struct local_symbol *) s)->lsy_section; 177433965Sjdp return s->bsym->section; 177533965Sjdp} 177633965Sjdp 177733965Sjdpvoid 177833965SjdpS_SET_SEGMENT (s, seg) 177933965Sjdp symbolS *s; 178033965Sjdp segT seg; 178133965Sjdp{ 178238889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 178338889Sjdp faults assigning back to const global symbols such as *ABS*, but it 178438889Sjdp shouldn't happen anyway. */ 178538889Sjdp 178660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 178760484Sobrien { 178860484Sobrien if (seg == reg_section) 178960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 179060484Sobrien else 179160484Sobrien { 179260484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 179360484Sobrien return; 179460484Sobrien } 179560484Sobrien } 179660484Sobrien 179738889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 179838889Sjdp { 179938889Sjdp if (s->bsym->section != seg) 180077298Sobrien abort (); 180138889Sjdp } 180238889Sjdp else 180338889Sjdp s->bsym->section = seg; 180433965Sjdp} 180533965Sjdp 180633965Sjdpvoid 180733965SjdpS_SET_EXTERNAL (s) 180833965Sjdp symbolS *s; 180933965Sjdp{ 181060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 181160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 181233965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 181333965Sjdp { 181433965Sjdp /* Let .weak override .global. */ 181533965Sjdp return; 181633965Sjdp } 181733965Sjdp s->bsym->flags |= BSF_GLOBAL; 181877298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 181933965Sjdp} 182033965Sjdp 182133965Sjdpvoid 182233965SjdpS_CLEAR_EXTERNAL (s) 182333965Sjdp symbolS *s; 182433965Sjdp{ 182560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 182660484Sobrien return; 182733965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 182833965Sjdp { 182933965Sjdp /* Let .weak override. */ 183033965Sjdp return; 183133965Sjdp } 183233965Sjdp s->bsym->flags |= BSF_LOCAL; 183377298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 183433965Sjdp} 183533965Sjdp 183633965Sjdpvoid 183733965SjdpS_SET_WEAK (s) 183833965Sjdp symbolS *s; 183933965Sjdp{ 184060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 184160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 184233965Sjdp s->bsym->flags |= BSF_WEAK; 184377298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 184433965Sjdp} 184533965Sjdp 184633965Sjdpvoid 184733965SjdpS_SET_NAME (s, name) 184833965Sjdp symbolS *s; 184933965Sjdp char *name; 185033965Sjdp{ 185160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 185260484Sobrien { 185360484Sobrien ((struct local_symbol *) s)->lsy_name = name; 185460484Sobrien return; 185560484Sobrien } 185633965Sjdp s->bsym->name = name; 185733965Sjdp} 185833965Sjdp#endif /* BFD_ASSEMBLER */ 185933965Sjdp 186060484Sobrien#ifdef SYMBOLS_NEED_BACKPOINTERS 186160484Sobrien 186260484Sobrien/* Return the previous symbol in a chain. */ 186360484Sobrien 186460484SobriensymbolS * 186560484Sobriensymbol_previous (s) 186660484Sobrien symbolS *s; 186760484Sobrien{ 186860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 186960484Sobrien abort (); 187060484Sobrien return s->sy_previous; 187160484Sobrien} 187260484Sobrien 187360484Sobrien#endif /* SYMBOLS_NEED_BACKPOINTERS */ 187460484Sobrien 187560484Sobrien/* Return the next symbol in a chain. */ 187660484Sobrien 187760484SobriensymbolS * 187860484Sobriensymbol_next (s) 187960484Sobrien symbolS *s; 188060484Sobrien{ 188160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 188260484Sobrien abort (); 188360484Sobrien return s->sy_next; 188460484Sobrien} 188560484Sobrien 188660484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 188760484Sobrien 188860484SobrienexpressionS * 188960484Sobriensymbol_get_value_expression (s) 189060484Sobrien symbolS *s; 189160484Sobrien{ 189260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 189360484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 189460484Sobrien return &s->sy_value; 189560484Sobrien} 189660484Sobrien 189760484Sobrien/* Set the value of a symbol to an expression. */ 189860484Sobrien 189933965Sjdpvoid 190060484Sobriensymbol_set_value_expression (s, exp) 190160484Sobrien symbolS *s; 190260484Sobrien const expressionS *exp; 190360484Sobrien{ 190460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 190560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 190660484Sobrien s->sy_value = *exp; 190760484Sobrien} 190860484Sobrien 190960484Sobrien/* Set the frag of a symbol. */ 191060484Sobrien 191160484Sobrienvoid 191260484Sobriensymbol_set_frag (s, f) 191360484Sobrien symbolS *s; 191460484Sobrien fragS *f; 191560484Sobrien{ 191660484Sobrien#ifdef BFD_ASSEMBLER 191760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 191860484Sobrien { 191960484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 192060484Sobrien return; 192160484Sobrien } 192260484Sobrien#endif 192360484Sobrien s->sy_frag = f; 192460484Sobrien} 192560484Sobrien 192660484Sobrien/* Return the frag of a symbol. */ 192760484Sobrien 192860484SobrienfragS * 192960484Sobriensymbol_get_frag (s) 193060484Sobrien symbolS *s; 193160484Sobrien{ 193260484Sobrien#ifdef BFD_ASSEMBLER 193360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 193460484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 193560484Sobrien#endif 193660484Sobrien return s->sy_frag; 193760484Sobrien} 193860484Sobrien 193960484Sobrien/* Mark a symbol as having been used. */ 194060484Sobrien 194160484Sobrienvoid 194260484Sobriensymbol_mark_used (s) 194360484Sobrien symbolS *s; 194460484Sobrien{ 194560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 194660484Sobrien return; 194760484Sobrien s->sy_used = 1; 194860484Sobrien} 194960484Sobrien 195060484Sobrien/* Clear the mark of whether a symbol has been used. */ 195160484Sobrien 195260484Sobrienvoid 195360484Sobriensymbol_clear_used (s) 195460484Sobrien symbolS *s; 195560484Sobrien{ 195660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 195760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 195860484Sobrien s->sy_used = 0; 195960484Sobrien} 196060484Sobrien 196160484Sobrien/* Return whether a symbol has been used. */ 196260484Sobrien 196360484Sobrienint 196460484Sobriensymbol_used_p (s) 196560484Sobrien symbolS *s; 196660484Sobrien{ 196760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 196860484Sobrien return 1; 196960484Sobrien return s->sy_used; 197060484Sobrien} 197160484Sobrien 197260484Sobrien/* Mark a symbol as having been used in a reloc. */ 197360484Sobrien 197460484Sobrienvoid 197560484Sobriensymbol_mark_used_in_reloc (s) 197660484Sobrien symbolS *s; 197760484Sobrien{ 197860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 198060484Sobrien s->sy_used_in_reloc = 1; 198160484Sobrien} 198260484Sobrien 198360484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 198460484Sobrien 198560484Sobrienvoid 198660484Sobriensymbol_clear_used_in_reloc (s) 198760484Sobrien symbolS *s; 198860484Sobrien{ 198960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 199060484Sobrien return; 199160484Sobrien s->sy_used_in_reloc = 0; 199260484Sobrien} 199360484Sobrien 199460484Sobrien/* Return whether a symbol has been used in a reloc. */ 199560484Sobrien 199660484Sobrienint 199760484Sobriensymbol_used_in_reloc_p (s) 199860484Sobrien symbolS *s; 199960484Sobrien{ 200060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 200160484Sobrien return 0; 200260484Sobrien return s->sy_used_in_reloc; 200360484Sobrien} 200460484Sobrien 200560484Sobrien/* Mark a symbol as an MRI common symbol. */ 200660484Sobrien 200760484Sobrienvoid 200860484Sobriensymbol_mark_mri_common (s) 200960484Sobrien symbolS *s; 201060484Sobrien{ 201160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 201260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 201360484Sobrien s->sy_mri_common = 1; 201460484Sobrien} 201560484Sobrien 201660484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 201760484Sobrien 201860484Sobrienvoid 201960484Sobriensymbol_clear_mri_common (s) 202060484Sobrien symbolS *s; 202160484Sobrien{ 202260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202360484Sobrien return; 202460484Sobrien s->sy_mri_common = 0; 202560484Sobrien} 202660484Sobrien 202760484Sobrien/* Return whether a symbol is an MRI common symbol. */ 202860484Sobrien 202960484Sobrienint 203060484Sobriensymbol_mri_common_p (s) 203160484Sobrien symbolS *s; 203260484Sobrien{ 203360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 203460484Sobrien return 0; 203560484Sobrien return s->sy_mri_common; 203660484Sobrien} 203760484Sobrien 203860484Sobrien/* Mark a symbol as having been written. */ 203960484Sobrien 204060484Sobrienvoid 204160484Sobriensymbol_mark_written (s) 204260484Sobrien symbolS *s; 204360484Sobrien{ 204460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 204560484Sobrien return; 204660484Sobrien s->written = 1; 204760484Sobrien} 204860484Sobrien 204960484Sobrien/* Clear the mark of whether a symbol has been written. */ 205060484Sobrien 205160484Sobrienvoid 205260484Sobriensymbol_clear_written (s) 205360484Sobrien symbolS *s; 205460484Sobrien{ 205560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 205660484Sobrien return; 205760484Sobrien s->written = 0; 205860484Sobrien} 205960484Sobrien 206060484Sobrien/* Return whether a symbol has been written. */ 206160484Sobrien 206260484Sobrienint 206360484Sobriensymbol_written_p (s) 206460484Sobrien symbolS *s; 206560484Sobrien{ 206660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 206760484Sobrien return 0; 206860484Sobrien return s->written; 206960484Sobrien} 207060484Sobrien 207160484Sobrien/* Mark a symbol has having been resolved. */ 207260484Sobrien 207360484Sobrienvoid 207460484Sobriensymbol_mark_resolved (s) 207560484Sobrien symbolS *s; 207660484Sobrien{ 207760484Sobrien#ifdef BFD_ASSEMBLER 207860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207960484Sobrien { 208060484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 208160484Sobrien return; 208260484Sobrien } 208360484Sobrien#endif 208460484Sobrien s->sy_resolved = 1; 208560484Sobrien} 208660484Sobrien 208760484Sobrien/* Return whether a symbol has been resolved. */ 208860484Sobrien 208960484Sobrienint 209060484Sobriensymbol_resolved_p (s) 209160484Sobrien symbolS *s; 209260484Sobrien{ 209360484Sobrien#ifdef BFD_ASSEMBLER 209460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 209560484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 209660484Sobrien#endif 209760484Sobrien return s->sy_resolved; 209860484Sobrien} 209960484Sobrien 210060484Sobrien/* Return whether a symbol is a section symbol. */ 210160484Sobrien 210260484Sobrienint 210360484Sobriensymbol_section_p (s) 210460484Sobrien symbolS *s ATTRIBUTE_UNUSED; 210560484Sobrien{ 210660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 210760484Sobrien return 0; 210860484Sobrien#ifdef BFD_ASSEMBLER 210960484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 211060484Sobrien#else 211177298Sobrien /* FIXME. */ 211260484Sobrien return 0; 211360484Sobrien#endif 211460484Sobrien} 211560484Sobrien 211660484Sobrien/* Return whether a symbol is equated to another symbol. */ 211760484Sobrien 211860484Sobrienint 211960484Sobriensymbol_equated_p (s) 212060484Sobrien symbolS *s; 212160484Sobrien{ 212260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212360484Sobrien return 0; 212460484Sobrien return s->sy_value.X_op == O_symbol; 212560484Sobrien} 212660484Sobrien 212760484Sobrien/* Return whether a symbol has a constant value. */ 212860484Sobrien 212960484Sobrienint 213060484Sobriensymbol_constant_p (s) 213160484Sobrien symbolS *s; 213260484Sobrien{ 213360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213460484Sobrien return 1; 213560484Sobrien return s->sy_value.X_op == O_constant; 213660484Sobrien} 213760484Sobrien 213860484Sobrien#ifdef BFD_ASSEMBLER 213960484Sobrien 214060484Sobrien/* Return the BFD symbol for a symbol. */ 214160484Sobrien 214260484Sobrienasymbol * 214360484Sobriensymbol_get_bfdsym (s) 214460484Sobrien symbolS *s; 214560484Sobrien{ 214660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 214760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 214860484Sobrien return s->bsym; 214960484Sobrien} 215060484Sobrien 215160484Sobrien/* Set the BFD symbol for a symbol. */ 215260484Sobrien 215360484Sobrienvoid 215460484Sobriensymbol_set_bfdsym (s, bsym) 215560484Sobrien symbolS *s; 215660484Sobrien asymbol *bsym; 215760484Sobrien{ 215860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 215960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 216060484Sobrien s->bsym = bsym; 216160484Sobrien} 216260484Sobrien 216360484Sobrien#endif /* BFD_ASSEMBLER */ 216460484Sobrien 216560484Sobrien#ifdef OBJ_SYMFIELD_TYPE 216660484Sobrien 216760484Sobrien/* Get a pointer to the object format information for a symbol. */ 216860484Sobrien 216960484SobrienOBJ_SYMFIELD_TYPE * 217060484Sobriensymbol_get_obj (s) 217160484Sobrien symbolS *s; 217260484Sobrien{ 217360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 217560484Sobrien return &s->sy_obj; 217660484Sobrien} 217760484Sobrien 217860484Sobrien/* Set the object format information for a symbol. */ 217960484Sobrien 218060484Sobrienvoid 218160484Sobriensymbol_set_obj (s, o) 218260484Sobrien symbolS *s; 218360484Sobrien OBJ_SYMFIELD_TYPE *o; 218460484Sobrien{ 218560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 218660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 218760484Sobrien s->sy_obj = *o; 218860484Sobrien} 218960484Sobrien 219060484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 219160484Sobrien 219260484Sobrien#ifdef TC_SYMFIELD_TYPE 219360484Sobrien 219460484Sobrien/* Get a pointer to the processor information for a symbol. */ 219560484Sobrien 219660484SobrienTC_SYMFIELD_TYPE * 219760484Sobriensymbol_get_tc (s) 219860484Sobrien symbolS *s; 219960484Sobrien{ 220060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 220160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 220260484Sobrien return &s->sy_tc; 220360484Sobrien} 220460484Sobrien 220560484Sobrien/* Set the processor information for a symbol. */ 220660484Sobrien 220760484Sobrienvoid 220860484Sobriensymbol_set_tc (s, o) 220960484Sobrien symbolS *s; 221060484Sobrien TC_SYMFIELD_TYPE *o; 221160484Sobrien{ 221260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 221360484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 221460484Sobrien s->sy_tc = *o; 221560484Sobrien} 221660484Sobrien 221760484Sobrien#endif /* TC_SYMFIELD_TYPE */ 221860484Sobrien 221960484Sobrienvoid 222033965Sjdpsymbol_begin () 222133965Sjdp{ 222233965Sjdp symbol_lastP = NULL; 222377298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 222433965Sjdp sy_hash = hash_new (); 222560484Sobrien#ifdef BFD_ASSEMBLER 222660484Sobrien local_hash = hash_new (); 222760484Sobrien#endif 222833965Sjdp 222933965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 223033965Sjdp#ifdef BFD_ASSEMBLER 223133965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 223233965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 223333965Sjdp#endif 223433965Sjdp#else 223577298Sobrien /* Can't initialise a union. Sigh. */ 223633965Sjdp S_SET_SEGMENT (&abs_symbol, absolute_section); 223733965Sjdp#endif 223833965Sjdp abs_symbol.sy_value.X_op = O_constant; 223933965Sjdp abs_symbol.sy_frag = &zero_address_frag; 224033965Sjdp 224133965Sjdp if (LOCAL_LABELS_FB) 224233965Sjdp fb_label_init (); 224333965Sjdp} 224433965Sjdp 224533965Sjdpint indent_level; 224633965Sjdp 224760484Sobrien/* Maximum indent level. 224860484Sobrien Available for modification inside a gdb session. */ 224960484Sobrienint max_indent_level = 8; 225060484Sobrien 225133965Sjdp#if 0 225233965Sjdp 225333965Sjdpstatic void 225433965Sjdpindent () 225533965Sjdp{ 225633965Sjdp printf ("%*s", indent_level * 4, ""); 225733965Sjdp} 225833965Sjdp 225933965Sjdp#endif 226033965Sjdp 226133965Sjdpvoid 226233965Sjdpprint_symbol_value_1 (file, sym) 226333965Sjdp FILE *file; 226433965Sjdp symbolS *sym; 226533965Sjdp{ 226633965Sjdp const char *name = S_GET_NAME (sym); 226733965Sjdp if (!name || !name[0]) 226833965Sjdp name = "(unnamed)"; 226933965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 227060484Sobrien 227160484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 227260484Sobrien { 227360484Sobrien#ifdef BFD_ASSEMBLER 227460484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 227560484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 227660484Sobrien && local_symbol_get_frag (locsym) != NULL) 227760484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 227860484Sobrien if (local_symbol_resolved_p (locsym)) 227960484Sobrien fprintf (file, " resolved"); 228060484Sobrien fprintf (file, " local"); 228160484Sobrien#endif 228260484Sobrien } 228360484Sobrien else 228460484Sobrien { 228560484Sobrien if (sym->sy_frag != &zero_address_frag) 228660484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 228760484Sobrien if (sym->written) 228860484Sobrien fprintf (file, " written"); 228960484Sobrien if (sym->sy_resolved) 229060484Sobrien fprintf (file, " resolved"); 229160484Sobrien else if (sym->sy_resolving) 229260484Sobrien fprintf (file, " resolving"); 229360484Sobrien if (sym->sy_used_in_reloc) 229460484Sobrien fprintf (file, " used-in-reloc"); 229560484Sobrien if (sym->sy_used) 229660484Sobrien fprintf (file, " used"); 229760484Sobrien if (S_IS_LOCAL (sym)) 229860484Sobrien fprintf (file, " local"); 229960484Sobrien if (S_IS_EXTERN (sym)) 230060484Sobrien fprintf (file, " extern"); 230160484Sobrien if (S_IS_DEBUG (sym)) 230260484Sobrien fprintf (file, " debug"); 230360484Sobrien if (S_IS_DEFINED (sym)) 230460484Sobrien fprintf (file, " defined"); 230560484Sobrien } 230633965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 230760484Sobrien if (symbol_resolved_p (sym)) 230833965Sjdp { 230933965Sjdp segT s = S_GET_SEGMENT (sym); 231033965Sjdp 231133965Sjdp if (s != undefined_section 231233965Sjdp && s != expr_section) 231333965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 231433965Sjdp } 231560484Sobrien else if (indent_level < max_indent_level 231660484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 231733965Sjdp { 231833965Sjdp indent_level++; 231933965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 232060484Sobrien#ifdef BFD_ASSEMBLER 232160484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 232260484Sobrien fprintf (file, "constant %lx", 232360484Sobrien (long) ((struct local_symbol *) sym)->lsy_offset); 232460484Sobrien else 232560484Sobrien#endif 232660484Sobrien print_expr_1 (file, &sym->sy_value); 232733965Sjdp fprintf (file, ">"); 232833965Sjdp indent_level--; 232933965Sjdp } 233033965Sjdp fflush (file); 233133965Sjdp} 233233965Sjdp 233333965Sjdpvoid 233433965Sjdpprint_symbol_value (sym) 233533965Sjdp symbolS *sym; 233633965Sjdp{ 233733965Sjdp indent_level = 0; 233833965Sjdp print_symbol_value_1 (stderr, sym); 233933965Sjdp fprintf (stderr, "\n"); 234033965Sjdp} 234133965Sjdp 234260484Sobrienstatic void 234360484Sobrienprint_binary (file, name, exp) 234460484Sobrien FILE *file; 234577298Sobrien const char *name; 234660484Sobrien expressionS *exp; 234760484Sobrien{ 234860484Sobrien indent_level++; 234960484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 235060484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 235160484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 235260484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 235360484Sobrien fprintf (file, ">"); 235460484Sobrien indent_level--; 235560484Sobrien} 235660484Sobrien 235733965Sjdpvoid 235833965Sjdpprint_expr_1 (file, exp) 235933965Sjdp FILE *file; 236033965Sjdp expressionS *exp; 236133965Sjdp{ 236233965Sjdp fprintf (file, "expr %lx ", (long) exp); 236333965Sjdp switch (exp->X_op) 236433965Sjdp { 236533965Sjdp case O_illegal: 236633965Sjdp fprintf (file, "illegal"); 236733965Sjdp break; 236833965Sjdp case O_absent: 236933965Sjdp fprintf (file, "absent"); 237033965Sjdp break; 237133965Sjdp case O_constant: 237233965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 237333965Sjdp break; 237433965Sjdp case O_symbol: 237533965Sjdp indent_level++; 237633965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 237733965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 237833965Sjdp fprintf (file, ">"); 237933965Sjdp maybe_print_addnum: 238033965Sjdp if (exp->X_add_number) 238133965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 238233965Sjdp (long) exp->X_add_number); 238333965Sjdp indent_level--; 238433965Sjdp break; 238533965Sjdp case O_register: 238633965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 238733965Sjdp break; 238833965Sjdp case O_big: 238933965Sjdp fprintf (file, "big"); 239033965Sjdp break; 239133965Sjdp case O_uminus: 239233965Sjdp fprintf (file, "uminus -<"); 239333965Sjdp indent_level++; 239433965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 239533965Sjdp fprintf (file, ">"); 239633965Sjdp goto maybe_print_addnum; 239733965Sjdp case O_bit_not: 239833965Sjdp fprintf (file, "bit_not"); 239933965Sjdp break; 240033965Sjdp case O_multiply: 240160484Sobrien print_binary (file, "multiply", exp); 240233965Sjdp break; 240333965Sjdp case O_divide: 240460484Sobrien print_binary (file, "divide", exp); 240533965Sjdp break; 240633965Sjdp case O_modulus: 240760484Sobrien print_binary (file, "modulus", exp); 240833965Sjdp break; 240933965Sjdp case O_left_shift: 241060484Sobrien print_binary (file, "lshift", exp); 241133965Sjdp break; 241233965Sjdp case O_right_shift: 241360484Sobrien print_binary (file, "rshift", exp); 241433965Sjdp break; 241533965Sjdp case O_bit_inclusive_or: 241660484Sobrien print_binary (file, "bit_ior", exp); 241733965Sjdp break; 241833965Sjdp case O_bit_exclusive_or: 241960484Sobrien print_binary (file, "bit_xor", exp); 242033965Sjdp break; 242133965Sjdp case O_bit_and: 242260484Sobrien print_binary (file, "bit_and", exp); 242333965Sjdp break; 242433965Sjdp case O_eq: 242560484Sobrien print_binary (file, "eq", exp); 242633965Sjdp break; 242733965Sjdp case O_ne: 242860484Sobrien print_binary (file, "ne", exp); 242933965Sjdp break; 243033965Sjdp case O_lt: 243160484Sobrien print_binary (file, "lt", exp); 243233965Sjdp break; 243333965Sjdp case O_le: 243460484Sobrien print_binary (file, "le", exp); 243533965Sjdp break; 243633965Sjdp case O_ge: 243760484Sobrien print_binary (file, "ge", exp); 243833965Sjdp break; 243933965Sjdp case O_gt: 244060484Sobrien print_binary (file, "gt", exp); 244133965Sjdp break; 244233965Sjdp case O_logical_and: 244360484Sobrien print_binary (file, "logical_and", exp); 244433965Sjdp break; 244533965Sjdp case O_logical_or: 244660484Sobrien print_binary (file, "logical_or", exp); 244733965Sjdp break; 244833965Sjdp case O_add: 244933965Sjdp indent_level++; 245033965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 245133965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 245233965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 245333965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 245433965Sjdp fprintf (file, ">"); 245533965Sjdp goto maybe_print_addnum; 245633965Sjdp case O_subtract: 245733965Sjdp indent_level++; 245833965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 245933965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 246033965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 246133965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 246233965Sjdp fprintf (file, ">"); 246333965Sjdp goto maybe_print_addnum; 246433965Sjdp default: 246533965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 246633965Sjdp break; 246733965Sjdp } 246833965Sjdp fflush (stdout); 246933965Sjdp} 247033965Sjdp 247133965Sjdpvoid 247233965Sjdpprint_expr (exp) 247333965Sjdp expressionS *exp; 247433965Sjdp{ 247533965Sjdp print_expr_1 (stderr, exp); 247633965Sjdp fprintf (stderr, "\n"); 247733965Sjdp} 247833965Sjdp 247933965Sjdpvoid 248033965Sjdpsymbol_print_statistics (file) 248133965Sjdp FILE *file; 248233965Sjdp{ 248333965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 248460484Sobrien#ifdef BFD_ASSEMBLER 248560484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 248660484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 248760484Sobrien local_symbol_count, local_symbol_conversion_count); 248860484Sobrien#endif 248933965Sjdp} 2490