133965Sjdp/* symbols.c -symbol table- 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3218822Sdim 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, 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; 62218822Sdim#ifdef USE_UNIQUE 63218822Sdim/* The name of an external symbol which is 64218822Sdim used to make weak PE symbol names unique. */ 65218822Sdimconst char * an_external_name; 66218822Sdim#endif 6733965Sjdp 68130561Sobrienstatic char *save_symbol_name (const char *); 69130561Sobrienstatic void fb_label_init (void); 70130561Sobrienstatic long dollar_label_instance (long); 71130561Sobrienstatic long fb_label_instance (long); 7233965Sjdp 73130561Sobrienstatic void print_binary (FILE *, const char *, expressionS *); 74130561Sobrienstatic void report_op_error (symbolS *, symbolS *, symbolS *); 7560484Sobrien 7677298Sobrien/* Return a pointer to a new symbol. Die if we can't make a new 7733965Sjdp symbol. Fill in the symbol's values. Add symbol to end of symbol 7833965Sjdp chain. 7977298Sobrien 8033965Sjdp This function should be called in the general case of creating a 8133965Sjdp symbol. However, if the output file symbol table has already been 8233965Sjdp set, and you are certain that this symbol won't be wanted in the 8333965Sjdp output file, you can call symbol_create. */ 8433965Sjdp 8533965SjdpsymbolS * 86130561Sobriensymbol_new (const char *name, segT segment, valueT valu, fragS *frag) 8733965Sjdp{ 8833965Sjdp symbolS *symbolP = symbol_create (name, segment, valu, frag); 8933965Sjdp 9077298Sobrien /* Link to end of symbol chain. */ 9133965Sjdp { 9233965Sjdp extern int symbol_table_frozen; 9333965Sjdp if (symbol_table_frozen) 9433965Sjdp abort (); 9533965Sjdp } 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 * 105130561Sobriensave_symbol_name (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 tc_canonicalize_symbol_name 11560484Sobrien ret = tc_canonicalize_symbol_name (ret); 11633965Sjdp#endif 11733965Sjdp 11833965Sjdp if (! symbols_case_sensitive) 11933965Sjdp { 12089857Sobrien char *s; 12133965Sjdp 12289857Sobrien for (s = ret; *s != '\0'; s++) 12389857Sobrien *s = TOUPPER (*s); 12433965Sjdp } 12533965Sjdp 12660484Sobrien return ret; 12760484Sobrien} 12860484Sobrien 12960484SobriensymbolS * 130130561Sobriensymbol_create (const char *name, /* It is copied, the caller can destroy/modify. */ 131130561Sobrien segT segment, /* Segment identifier (SEG_<something>). */ 132130561Sobrien valueT valu, /* Symbol value. */ 133130561Sobrien fragS *frag /* Associated fragment. */) 13460484Sobrien{ 13560484Sobrien char *preserved_copy_of_name; 13660484Sobrien symbolS *symbolP; 13760484Sobrien 13860484Sobrien preserved_copy_of_name = save_symbol_name (name); 13960484Sobrien 14033965Sjdp symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS)); 14133965Sjdp 14277298Sobrien /* symbol must be born in some fixed state. This seems as good as any. */ 14333965Sjdp memset (symbolP, 0, sizeof (symbolS)); 14433965Sjdp 14533965Sjdp symbolP->bsym = bfd_make_empty_symbol (stdoutput); 14633965Sjdp if (symbolP->bsym == NULL) 147218822Sdim as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ())); 14833965Sjdp S_SET_NAME (symbolP, preserved_copy_of_name); 14933965Sjdp 15033965Sjdp S_SET_SEGMENT (symbolP, segment); 15133965Sjdp S_SET_VALUE (symbolP, valu); 15233965Sjdp symbol_clear_list_pointers (symbolP); 15333965Sjdp 15433965Sjdp symbolP->sy_frag = frag; 15533965Sjdp 15633965Sjdp obj_symbol_new_hook (symbolP); 15733965Sjdp 15833965Sjdp#ifdef tc_symbol_new_hook 15933965Sjdp tc_symbol_new_hook (symbolP); 16033965Sjdp#endif 16133965Sjdp 16233965Sjdp return symbolP; 16333965Sjdp} 16433965Sjdp 16533965Sjdp 16660484Sobrien/* Local symbol support. If we can get away with it, we keep only a 16760484Sobrien small amount of information for local symbols. */ 16860484Sobrien 169130561Sobrienstatic symbolS *local_symbol_convert (struct local_symbol *); 17060484Sobrien 17160484Sobrien/* Used for statistics. */ 17260484Sobrien 17360484Sobrienstatic unsigned long local_symbol_count; 17460484Sobrienstatic unsigned long local_symbol_conversion_count; 17560484Sobrien 17660484Sobrien/* This macro is called with a symbol argument passed by reference. 17760484Sobrien It returns whether this is a local symbol. If necessary, it 17860484Sobrien changes its argument to the real symbol. */ 17960484Sobrien 18060484Sobrien#define LOCAL_SYMBOL_CHECK(s) \ 18160484Sobrien (s->bsym == NULL \ 18260484Sobrien ? (local_symbol_converted_p ((struct local_symbol *) s) \ 18360484Sobrien ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s), \ 18460484Sobrien 0) \ 18560484Sobrien : 1) \ 18660484Sobrien : 0) 18760484Sobrien 18860484Sobrien/* Create a local symbol and insert it into the local hash table. */ 18960484Sobrien 190218822Sdimstatic struct local_symbol * 191130561Sobrienlocal_symbol_make (const char *name, segT section, valueT value, fragS *frag) 19260484Sobrien{ 19360484Sobrien char *name_copy; 19460484Sobrien struct local_symbol *ret; 19560484Sobrien 19660484Sobrien ++local_symbol_count; 19760484Sobrien 19860484Sobrien name_copy = save_symbol_name (name); 19960484Sobrien 20060484Sobrien ret = (struct local_symbol *) obstack_alloc (¬es, sizeof *ret); 20160484Sobrien ret->lsy_marker = NULL; 20260484Sobrien ret->lsy_name = name_copy; 20360484Sobrien ret->lsy_section = section; 20460484Sobrien local_symbol_set_frag (ret, frag); 20589857Sobrien ret->lsy_value = value; 20660484Sobrien 20760484Sobrien hash_jam (local_hash, name_copy, (PTR) ret); 20860484Sobrien 20960484Sobrien return ret; 21060484Sobrien} 21160484Sobrien 21260484Sobrien/* Convert a local symbol into a real symbol. Note that we do not 21360484Sobrien reclaim the space used by the local symbol. */ 21460484Sobrien 21560484Sobrienstatic symbolS * 216130561Sobrienlocal_symbol_convert (struct local_symbol *locsym) 21760484Sobrien{ 21860484Sobrien symbolS *ret; 21960484Sobrien 22060484Sobrien assert (locsym->lsy_marker == NULL); 22160484Sobrien if (local_symbol_converted_p (locsym)) 22260484Sobrien return local_symbol_get_real_symbol (locsym); 22360484Sobrien 22460484Sobrien ++local_symbol_conversion_count; 22560484Sobrien 22689857Sobrien ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value, 22760484Sobrien local_symbol_get_frag (locsym)); 22860484Sobrien 22960484Sobrien if (local_symbol_resolved_p (locsym)) 23060484Sobrien ret->sy_resolved = 1; 23160484Sobrien 23260484Sobrien /* Local symbols are always either defined or used. */ 23360484Sobrien ret->sy_used = 1; 23460484Sobrien 23589857Sobrien#ifdef TC_LOCAL_SYMFIELD_CONVERT 23689857Sobrien TC_LOCAL_SYMFIELD_CONVERT (locsym, ret); 23789857Sobrien#endif 23889857Sobrien 23960484Sobrien symbol_table_insert (ret); 24060484Sobrien 24160484Sobrien local_symbol_mark_converted (locsym); 24260484Sobrien local_symbol_set_real_symbol (locsym, ret); 24360484Sobrien 24460484Sobrien hash_jam (local_hash, locsym->lsy_name, NULL); 24560484Sobrien 24660484Sobrien return ret; 24760484Sobrien} 24860484Sobrien 24977298Sobrien/* We have just seen "<name>:". 25077298Sobrien Creates a struct symbol unless it already exists. 25160484Sobrien 25277298Sobrien Gripes if we are redefining a symbol incompatibly (and ignores it). */ 25377298Sobrien 25433965SjdpsymbolS * 255130561Sobriencolon (/* Just seen "x:" - rattle symbols & frags. */ 256130561Sobrien const char *sym_name /* Symbol name, as a cannonical string. */ 257130561Sobrien /* We copy this string: OK to alter later. */) 25833965Sjdp{ 25977298Sobrien register symbolS *symbolP; /* Symbol we are working with. */ 26033965Sjdp 26133965Sjdp /* Sun local labels go out of scope whenever a non-local symbol is 26233965Sjdp defined. */ 263218822Sdim if (LOCAL_LABELS_DOLLAR 264218822Sdim && !bfd_is_local_label_name (stdoutput, sym_name)) 265218822Sdim dollar_label_clear (); 26633965Sjdp 26733965Sjdp#ifndef WORKING_DOT_WORD 26833965Sjdp if (new_broken_words) 26933965Sjdp { 27033965Sjdp struct broken_word *a; 27133965Sjdp int possible_bytes; 27233965Sjdp fragS *frag_tmp; 27333965Sjdp char *frag_opcode; 27433965Sjdp 275130561Sobrien if (now_seg == absolute_section) 276130561Sobrien { 277130561Sobrien as_bad (_("cannot define symbol `%s' in absolute section"), sym_name); 278130561Sobrien return NULL; 279130561Sobrien } 280130561Sobrien 28133965Sjdp possible_bytes = (md_short_jump_size 28233965Sjdp + new_broken_words * md_long_jump_size); 28333965Sjdp 28433965Sjdp frag_tmp = frag_now; 28533965Sjdp frag_opcode = frag_var (rs_broken_word, 28633965Sjdp possible_bytes, 28733965Sjdp possible_bytes, 28833965Sjdp (relax_substateT) 0, 28933965Sjdp (symbolS *) broken_words, 29033965Sjdp (offsetT) 0, 29133965Sjdp NULL); 29233965Sjdp 29377298Sobrien /* We want to store the pointer to where to insert the jump 29477298Sobrien table in the fr_opcode of the rs_broken_word frag. This 29577298Sobrien requires a little hackery. */ 29633965Sjdp while (frag_tmp 29733965Sjdp && (frag_tmp->fr_type != rs_broken_word 29833965Sjdp || frag_tmp->fr_opcode)) 29933965Sjdp frag_tmp = frag_tmp->fr_next; 30033965Sjdp know (frag_tmp); 30133965Sjdp frag_tmp->fr_opcode = frag_opcode; 30233965Sjdp new_broken_words = 0; 30333965Sjdp 30433965Sjdp for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word) 30533965Sjdp a->dispfrag = frag_tmp; 30633965Sjdp } 30733965Sjdp#endif /* WORKING_DOT_WORD */ 30833965Sjdp 30933965Sjdp if ((symbolP = symbol_find (sym_name)) != 0) 31033965Sjdp { 311218822Sdim S_CLEAR_WEAKREFR (symbolP); 31233965Sjdp#ifdef RESOLVE_SYMBOL_REDEFINITION 31333965Sjdp if (RESOLVE_SYMBOL_REDEFINITION (symbolP)) 31433965Sjdp return symbolP; 31533965Sjdp#endif 31677298Sobrien /* Now check for undefined symbols. */ 31760484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 31833965Sjdp { 31960484Sobrien struct local_symbol *locsym = (struct local_symbol *) symbolP; 32060484Sobrien 32160484Sobrien if (locsym->lsy_section != undefined_section 32260484Sobrien && (local_symbol_get_frag (locsym) != frag_now 32360484Sobrien || locsym->lsy_section != now_seg 32489857Sobrien || locsym->lsy_value != frag_now_fix ())) 32560484Sobrien { 32689857Sobrien as_bad (_("symbol `%s' is already defined"), sym_name); 32760484Sobrien return symbolP; 32860484Sobrien } 32960484Sobrien 33060484Sobrien locsym->lsy_section = now_seg; 33160484Sobrien local_symbol_set_frag (locsym, frag_now); 33289857Sobrien locsym->lsy_value = frag_now_fix (); 33360484Sobrien } 334218822Sdim else if (!(S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) 335218822Sdim || S_IS_COMMON (symbolP) 336218822Sdim || S_IS_VOLATILE (symbolP)) 33760484Sobrien { 338218822Sdim if (S_IS_VOLATILE (symbolP)) 339218822Sdim { 340218822Sdim symbolP = symbol_clone (symbolP, 1); 341218822Sdim S_SET_VALUE (symbolP, 0); 342218822Sdim S_CLEAR_VOLATILE (symbolP); 343218822Sdim } 34433965Sjdp if (S_GET_VALUE (symbolP) == 0) 34533965Sjdp { 34633965Sjdp symbolP->sy_frag = frag_now; 34733965Sjdp#ifdef OBJ_VMS 34877298Sobrien S_SET_OTHER (symbolP, const_flag); 34933965Sjdp#endif 35033965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 35133965Sjdp S_SET_SEGMENT (symbolP, now_seg); 35233965Sjdp#ifdef N_UNDF 35333965Sjdp know (N_UNDF == 0); 35477298Sobrien#endif /* if we have one, it better be zero. */ 35533965Sjdp 35633965Sjdp } 35733965Sjdp else 35833965Sjdp { 35977298Sobrien /* There are still several cases to check: 36033965Sjdp 36177298Sobrien A .comm/.lcomm symbol being redefined as initialized 36277298Sobrien data is OK 36377298Sobrien 36477298Sobrien A .comm/.lcomm symbol being redefined with a larger 36577298Sobrien size is also OK 36677298Sobrien 36777298Sobrien This only used to be allowed on VMS gas, but Sun cc 36877298Sobrien on the sparc also depends on it. */ 36977298Sobrien 37033965Sjdp if (((!S_IS_DEBUG (symbolP) 37133965Sjdp && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)) 37233965Sjdp && S_IS_EXTERNAL (symbolP)) 37333965Sjdp || S_GET_SEGMENT (symbolP) == bss_section) 37433965Sjdp && (now_seg == data_section 375218822Sdim || now_seg == bss_section 37633965Sjdp || now_seg == S_GET_SEGMENT (symbolP))) 37733965Sjdp { 37877298Sobrien /* Select which of the 2 cases this is. */ 37933965Sjdp if (now_seg != data_section) 38033965Sjdp { 38177298Sobrien /* New .comm for prev .comm symbol. 38277298Sobrien 38377298Sobrien If the new size is larger we just change its 38477298Sobrien value. If the new size is smaller, we ignore 38577298Sobrien this symbol. */ 38633965Sjdp if (S_GET_VALUE (symbolP) 38733965Sjdp < ((unsigned) frag_now_fix ())) 38833965Sjdp { 38933965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 39033965Sjdp } 39133965Sjdp } 39233965Sjdp else 39333965Sjdp { 39433965Sjdp /* It is a .comm/.lcomm being converted to initialized 39533965Sjdp data. */ 39633965Sjdp symbolP->sy_frag = frag_now; 39733965Sjdp#ifdef OBJ_VMS 39877298Sobrien S_SET_OTHER (symbolP, const_flag); 39933965Sjdp#endif 40033965Sjdp S_SET_VALUE (symbolP, (valueT) frag_now_fix ()); 40177298Sobrien S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit. */ 40233965Sjdp } 40333965Sjdp } 40433965Sjdp else 40533965Sjdp { 40660484Sobrien#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \ 40760484Sobrien && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT)) 40860484Sobrien static const char *od_buf = ""; 40933965Sjdp#else 41060484Sobrien char od_buf[100]; 41160484Sobrien od_buf[0] = '\0'; 41260484Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 413104834Sobrien sprintf (od_buf, "%d.%d.", 414104834Sobrien S_GET_OTHER (symbolP), 415104834Sobrien S_GET_DESC (symbolP)); 41660484Sobrien#endif 41789857Sobrien as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"), 41833965Sjdp sym_name, 41933965Sjdp segment_name (S_GET_SEGMENT (symbolP)), 42060484Sobrien od_buf, 42133965Sjdp (long) S_GET_VALUE (symbolP)); 42233965Sjdp } 42377298Sobrien } /* if the undefined symbol has no value */ 42433965Sjdp } 42533965Sjdp else 42633965Sjdp { 42777298Sobrien /* Don't blow up if the definition is the same. */ 42833965Sjdp if (!(frag_now == symbolP->sy_frag 42933965Sjdp && S_GET_VALUE (symbolP) == frag_now_fix () 43033965Sjdp && S_GET_SEGMENT (symbolP) == now_seg)) 431218822Sdim { 432218822Sdim as_bad (_("symbol `%s' is already defined"), sym_name); 433218822Sdim symbolP = symbol_clone (symbolP, 0); 434218822Sdim } 43577298Sobrien } 43633965Sjdp 43733965Sjdp } 43860484Sobrien else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name)) 43960484Sobrien { 44060484Sobrien symbolP = (symbolS *) local_symbol_make (sym_name, now_seg, 44160484Sobrien (valueT) frag_now_fix (), 44260484Sobrien frag_now); 44360484Sobrien } 44433965Sjdp else 44533965Sjdp { 44633965Sjdp symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (), 44733965Sjdp frag_now); 44833965Sjdp#ifdef OBJ_VMS 44933965Sjdp S_SET_OTHER (symbolP, const_flag); 45033965Sjdp#endif /* OBJ_VMS */ 45133965Sjdp 45233965Sjdp symbol_table_insert (symbolP); 45377298Sobrien } 45433965Sjdp 45533965Sjdp if (mri_common_symbol != NULL) 45633965Sjdp { 45733965Sjdp /* This symbol is actually being defined within an MRI common 458130561Sobrien section. This requires special handling. */ 45960484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 46060484Sobrien symbolP = local_symbol_convert ((struct local_symbol *) symbolP); 46133965Sjdp symbolP->sy_value.X_op = O_symbol; 46233965Sjdp symbolP->sy_value.X_add_symbol = mri_common_symbol; 46333965Sjdp symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol); 46433965Sjdp symbolP->sy_frag = &zero_address_frag; 46533965Sjdp S_SET_SEGMENT (symbolP, expr_section); 46633965Sjdp symbolP->sy_mri_common = 1; 46733965Sjdp } 46833965Sjdp 46933965Sjdp#ifdef tc_frob_label 47033965Sjdp tc_frob_label (symbolP); 47133965Sjdp#endif 47233965Sjdp#ifdef obj_frob_label 47333965Sjdp obj_frob_label (symbolP); 47433965Sjdp#endif 47533965Sjdp 47633965Sjdp return symbolP; 47733965Sjdp} 47833965Sjdp 47977298Sobrien/* Die if we can't insert the symbol. */ 48033965Sjdp 48177298Sobrienvoid 482130561Sobriensymbol_table_insert (symbolS *symbolP) 48333965Sjdp{ 48433965Sjdp register const char *error_string; 48533965Sjdp 48633965Sjdp know (symbolP); 48733965Sjdp know (S_GET_NAME (symbolP)); 48833965Sjdp 48960484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 49060484Sobrien { 49160484Sobrien error_string = hash_jam (local_hash, S_GET_NAME (symbolP), 49260484Sobrien (PTR) symbolP); 49360484Sobrien if (error_string != NULL) 49489857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 49560484Sobrien S_GET_NAME (symbolP), error_string); 49660484Sobrien return; 49760484Sobrien } 49860484Sobrien 49933965Sjdp if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP))) 50033965Sjdp { 50189857Sobrien as_fatal (_("inserting \"%s\" into symbol table failed: %s"), 50233965Sjdp S_GET_NAME (symbolP), error_string); 50377298Sobrien } /* on error */ 50477298Sobrien} 50533965Sjdp 50677298Sobrien/* If a symbol name does not exist, create it as undefined, and insert 50777298Sobrien it into the symbol table. Return a pointer to it. */ 50877298Sobrien 50933965SjdpsymbolS * 510130561Sobriensymbol_find_or_make (const char *name) 51133965Sjdp{ 51233965Sjdp register symbolS *symbolP; 51333965Sjdp 51433965Sjdp symbolP = symbol_find (name); 51533965Sjdp 51633965Sjdp if (symbolP == NULL) 51733965Sjdp { 51860484Sobrien if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name)) 51960484Sobrien { 52060484Sobrien symbolP = md_undefined_symbol ((char *) name); 52160484Sobrien if (symbolP != NULL) 52260484Sobrien return symbolP; 52360484Sobrien 52460484Sobrien symbolP = (symbolS *) local_symbol_make (name, undefined_section, 52560484Sobrien (valueT) 0, 52660484Sobrien &zero_address_frag); 52760484Sobrien return symbolP; 52860484Sobrien } 52960484Sobrien 53033965Sjdp symbolP = symbol_make (name); 53133965Sjdp 53233965Sjdp symbol_table_insert (symbolP); 53333965Sjdp } /* if symbol wasn't found */ 53433965Sjdp 53533965Sjdp return (symbolP); 53677298Sobrien} 53733965Sjdp 53833965SjdpsymbolS * 539130561Sobriensymbol_make (const char *name) 54033965Sjdp{ 54133965Sjdp symbolS *symbolP; 54233965Sjdp 54377298Sobrien /* Let the machine description default it, e.g. for register names. */ 54433965Sjdp symbolP = md_undefined_symbol ((char *) name); 54533965Sjdp 54633965Sjdp if (!symbolP) 54733965Sjdp symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag); 54833965Sjdp 54933965Sjdp return (symbolP); 55077298Sobrien} 55133965Sjdp 552130561SobriensymbolS * 553218822Sdimsymbol_clone (symbolS *orgsymP, int replace) 554218822Sdim{ 555218822Sdim symbolS *newsymP; 556218822Sdim asymbol *bsymorg, *bsymnew; 557218822Sdim 558218822Sdim /* Running local_symbol_convert on a clone that's not the one currently 559218822Sdim in local_hash would incorrectly replace the hash entry. Thus the 560218822Sdim symbol must be converted here. Note that the rest of the function 561218822Sdim depends on not encountering an unconverted symbol. */ 562218822Sdim if (LOCAL_SYMBOL_CHECK (orgsymP)) 563218822Sdim orgsymP = local_symbol_convert ((struct local_symbol *) orgsymP); 564218822Sdim bsymorg = orgsymP->bsym; 565218822Sdim 566218822Sdim newsymP = obstack_alloc (¬es, sizeof (*newsymP)); 567218822Sdim *newsymP = *orgsymP; 568218822Sdim bsymnew = bfd_make_empty_symbol (bfd_asymbol_bfd (bsymorg)); 569218822Sdim if (bsymnew == NULL) 570218822Sdim as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ())); 571218822Sdim newsymP->bsym = bsymnew; 572218822Sdim bsymnew->name = bsymorg->name; 573218822Sdim bsymnew->flags = bsymorg->flags; 574218822Sdim bsymnew->section = bsymorg->section; 575218822Sdim bfd_copy_private_symbol_data (bfd_asymbol_bfd (bsymorg), bsymorg, 576218822Sdim bfd_asymbol_bfd (bsymnew), bsymnew); 577218822Sdim 578218822Sdim#ifdef obj_symbol_clone_hook 579218822Sdim obj_symbol_clone_hook (newsymP, orgsymP); 580218822Sdim#endif 581218822Sdim 582218822Sdim#ifdef tc_symbol_clone_hook 583218822Sdim tc_symbol_clone_hook (newsymP, orgsymP); 584218822Sdim#endif 585218822Sdim 586218822Sdim if (replace) 587218822Sdim { 588218822Sdim if (symbol_rootP == orgsymP) 589218822Sdim symbol_rootP = newsymP; 590218822Sdim else if (orgsymP->sy_previous) 591218822Sdim { 592218822Sdim orgsymP->sy_previous->sy_next = newsymP; 593218822Sdim orgsymP->sy_previous = NULL; 594218822Sdim } 595218822Sdim if (symbol_lastP == orgsymP) 596218822Sdim symbol_lastP = newsymP; 597218822Sdim else if (orgsymP->sy_next) 598218822Sdim orgsymP->sy_next->sy_previous = newsymP; 599218822Sdim orgsymP->sy_previous = orgsymP->sy_next = orgsymP; 600218822Sdim debug_verify_symchain (symbol_rootP, symbol_lastP); 601218822Sdim 602218822Sdim symbol_table_insert (newsymP); 603218822Sdim } 604218822Sdim else 605218822Sdim newsymP->sy_previous = newsymP->sy_next = newsymP; 606218822Sdim 607218822Sdim return newsymP; 608218822Sdim} 609218822Sdim 610218822Sdim/* Referenced symbols, if they are forward references, need to be cloned 611218822Sdim (without replacing the original) so that the value of the referenced 612218822Sdim symbols at the point of use . */ 613218822Sdim 614218822Sdim#undef symbol_clone_if_forward_ref 615218822SdimsymbolS * 616218822Sdimsymbol_clone_if_forward_ref (symbolS *symbolP, int is_forward) 617218822Sdim{ 618218822Sdim if (symbolP && !LOCAL_SYMBOL_CHECK (symbolP)) 619218822Sdim { 620218822Sdim symbolS *add_symbol = symbolP->sy_value.X_add_symbol; 621218822Sdim symbolS *op_symbol = symbolP->sy_value.X_op_symbol; 622218822Sdim 623218822Sdim if (symbolP->sy_forward_ref) 624218822Sdim is_forward = 1; 625218822Sdim 626218822Sdim if (is_forward) 627218822Sdim { 628218822Sdim /* assign_symbol() clones volatile symbols; pre-existing expressions 629218822Sdim hold references to the original instance, but want the current 630218822Sdim value. Just repeat the lookup. */ 631218822Sdim if (add_symbol && S_IS_VOLATILE (add_symbol)) 632218822Sdim add_symbol = symbol_find_exact (S_GET_NAME (add_symbol)); 633218822Sdim if (op_symbol && S_IS_VOLATILE (op_symbol)) 634218822Sdim op_symbol = symbol_find_exact (S_GET_NAME (op_symbol)); 635218822Sdim } 636218822Sdim 637218822Sdim /* Re-using sy_resolving here, as this routine cannot get called from 638218822Sdim symbol resolution code. */ 639218822Sdim if (symbolP->bsym->section == expr_section && !symbolP->sy_resolving) 640218822Sdim { 641218822Sdim symbolP->sy_resolving = 1; 642218822Sdim add_symbol = symbol_clone_if_forward_ref (add_symbol, is_forward); 643218822Sdim op_symbol = symbol_clone_if_forward_ref (op_symbol, is_forward); 644218822Sdim symbolP->sy_resolving = 0; 645218822Sdim } 646218822Sdim 647218822Sdim if (symbolP->sy_forward_ref 648218822Sdim || add_symbol != symbolP->sy_value.X_add_symbol 649218822Sdim || op_symbol != symbolP->sy_value.X_op_symbol) 650218822Sdim symbolP = symbol_clone (symbolP, 0); 651218822Sdim 652218822Sdim symbolP->sy_value.X_add_symbol = add_symbol; 653218822Sdim symbolP->sy_value.X_op_symbol = op_symbol; 654218822Sdim } 655218822Sdim 656218822Sdim return symbolP; 657218822Sdim} 658218822Sdim 659218822SdimsymbolS * 660130561Sobriensymbol_temp_new (segT seg, valueT ofs, fragS *frag) 661130561Sobrien{ 662130561Sobrien return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag); 663130561Sobrien} 664130561Sobrien 665130561SobriensymbolS * 666130561Sobriensymbol_temp_new_now (void) 667130561Sobrien{ 668130561Sobrien return symbol_temp_new (now_seg, frag_now_fix (), frag_now); 669130561Sobrien} 670130561Sobrien 671130561SobriensymbolS * 672130561Sobriensymbol_temp_make (void) 673130561Sobrien{ 674130561Sobrien return symbol_make (FAKE_LABEL_NAME); 675130561Sobrien} 676130561Sobrien 67777298Sobrien/* Implement symbol table lookup. 67877298Sobrien In: A symbol's name as a string: '\0' can't be part of a symbol name. 67977298Sobrien Out: NULL if the name was not in the symbol table, else the address 68077298Sobrien of a struct symbol associated with that name. */ 68133965Sjdp 68233965SjdpsymbolS * 683218822Sdimsymbol_find_exact (const char *name) 68433965Sjdp{ 685218822Sdim return symbol_find_exact_noref (name, 0); 68677298Sobrien} 68733965Sjdp 68833965SjdpsymbolS * 689218822Sdimsymbol_find_exact_noref (const char *name, int noref) 690104834Sobrien{ 691218822Sdim struct local_symbol *locsym; 692218822Sdim symbolS* sym; 693104834Sobrien 694218822Sdim locsym = (struct local_symbol *) hash_find (local_hash, name); 695218822Sdim if (locsym != NULL) 696218822Sdim return (symbolS *) locsym; 697104834Sobrien 698218822Sdim sym = ((symbolS *) hash_find (sy_hash, name)); 699218822Sdim 700218822Sdim /* Any references to the symbol, except for the reference in 701218822Sdim .weakref, must clear this flag, such that the symbol does not 702218822Sdim turn into a weak symbol. Note that we don't have to handle the 703218822Sdim local_symbol case, since a weakrefd is always promoted out of the 704218822Sdim local_symbol table when it is turned into a weak symbol. */ 705218822Sdim if (sym && ! noref) 706218822Sdim S_CLEAR_WEAKREFD (sym); 707218822Sdim 708218822Sdim return sym; 709104834Sobrien} 710104834Sobrien 711104834SobriensymbolS * 712218822Sdimsymbol_find (const char *name) 71333965Sjdp{ 714218822Sdim return symbol_find_noref (name, 0); 715218822Sdim} 71633965Sjdp 717218822SdimsymbolS * 718218822Sdimsymbol_find_noref (const char *name, int noref) 719218822Sdim{ 72033965Sjdp#ifdef tc_canonicalize_symbol_name 72133965Sjdp { 72233965Sjdp char *copy; 72360484Sobrien size_t len = strlen (name) + 1; 72433965Sjdp 72560484Sobrien copy = (char *) alloca (len); 72660484Sobrien memcpy (copy, name, len); 72733965Sjdp name = tc_canonicalize_symbol_name (copy); 72833965Sjdp } 72933965Sjdp#endif 73033965Sjdp 73133965Sjdp if (! symbols_case_sensitive) 73233965Sjdp { 73360484Sobrien char *copy; 73460484Sobrien const char *orig; 73560484Sobrien unsigned char c; 73633965Sjdp 73760484Sobrien orig = name; 73860484Sobrien name = copy = (char *) alloca (strlen (name) + 1); 73960484Sobrien 74060484Sobrien while ((c = *orig++) != '\0') 74160484Sobrien { 74289857Sobrien *copy++ = TOUPPER (c); 74360484Sobrien } 74460484Sobrien *copy = '\0'; 74533965Sjdp } 74633965Sjdp 747218822Sdim return symbol_find_exact_noref (name, noref); 74833965Sjdp} 74933965Sjdp 75077298Sobrien/* Once upon a time, symbols were kept in a singly linked list. At 75177298Sobrien least coff needs to be able to rearrange them from time to time, for 75277298Sobrien which a doubly linked list is much more convenient. Loic did these 75377298Sobrien as macros which seemed dangerous to me so they're now functions. 75477298Sobrien xoxorich. */ 75533965Sjdp 75677298Sobrien/* Link symbol ADDME after symbol TARGET in the chain. */ 75777298Sobrien 75877298Sobrienvoid 759130561Sobriensymbol_append (symbolS *addme, symbolS *target, 760130561Sobrien symbolS **rootPP, symbolS **lastPP) 76133965Sjdp{ 76260484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 76360484Sobrien abort (); 76460484Sobrien if (target != NULL && LOCAL_SYMBOL_CHECK (target)) 76560484Sobrien abort (); 76660484Sobrien 76733965Sjdp if (target == NULL) 76833965Sjdp { 76933965Sjdp know (*rootPP == NULL); 77033965Sjdp know (*lastPP == NULL); 77133965Sjdp addme->sy_next = NULL; 77233965Sjdp addme->sy_previous = NULL; 77333965Sjdp *rootPP = addme; 77433965Sjdp *lastPP = addme; 77533965Sjdp return; 77677298Sobrien } /* if the list is empty */ 77733965Sjdp 77833965Sjdp if (target->sy_next != NULL) 77933965Sjdp { 78033965Sjdp target->sy_next->sy_previous = addme; 78133965Sjdp } 78233965Sjdp else 78333965Sjdp { 78433965Sjdp know (*lastPP == target); 78533965Sjdp *lastPP = addme; 78677298Sobrien } /* if we have a next */ 78733965Sjdp 78833965Sjdp addme->sy_next = target->sy_next; 78933965Sjdp target->sy_next = addme; 79033965Sjdp addme->sy_previous = target; 79133965Sjdp 79233965Sjdp debug_verify_symchain (symbol_rootP, symbol_lastP); 79333965Sjdp} 79433965Sjdp 79577298Sobrien/* Set the chain pointers of SYMBOL to null. */ 79677298Sobrien 79777298Sobrienvoid 798130561Sobriensymbol_clear_list_pointers (symbolS *symbolP) 79933965Sjdp{ 80060484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 80160484Sobrien abort (); 80233965Sjdp symbolP->sy_next = NULL; 80333965Sjdp symbolP->sy_previous = NULL; 80433965Sjdp} 80533965Sjdp 80677298Sobrien/* Remove SYMBOLP from the list. */ 80777298Sobrien 80877298Sobrienvoid 809130561Sobriensymbol_remove (symbolS *symbolP, symbolS **rootPP, symbolS **lastPP) 81033965Sjdp{ 81160484Sobrien if (LOCAL_SYMBOL_CHECK (symbolP)) 81260484Sobrien abort (); 81360484Sobrien 81433965Sjdp if (symbolP == *rootPP) 81533965Sjdp { 81633965Sjdp *rootPP = symbolP->sy_next; 81777298Sobrien } /* if it was the root */ 81833965Sjdp 81933965Sjdp if (symbolP == *lastPP) 82033965Sjdp { 82133965Sjdp *lastPP = symbolP->sy_previous; 82277298Sobrien } /* if it was the tail */ 82333965Sjdp 82433965Sjdp if (symbolP->sy_next != NULL) 82533965Sjdp { 82633965Sjdp symbolP->sy_next->sy_previous = symbolP->sy_previous; 82777298Sobrien } /* if not last */ 82833965Sjdp 82933965Sjdp if (symbolP->sy_previous != NULL) 83033965Sjdp { 83133965Sjdp symbolP->sy_previous->sy_next = symbolP->sy_next; 83277298Sobrien } /* if not first */ 83333965Sjdp 83433965Sjdp debug_verify_symchain (*rootPP, *lastPP); 83533965Sjdp} 83633965Sjdp 83777298Sobrien/* Link symbol ADDME before symbol TARGET in the chain. */ 83877298Sobrien 83977298Sobrienvoid 840130561Sobriensymbol_insert (symbolS *addme, symbolS *target, 841130561Sobrien symbolS **rootPP, symbolS **lastPP ATTRIBUTE_UNUSED) 84233965Sjdp{ 84360484Sobrien if (LOCAL_SYMBOL_CHECK (addme)) 84460484Sobrien abort (); 84560484Sobrien if (LOCAL_SYMBOL_CHECK (target)) 84660484Sobrien abort (); 84760484Sobrien 84833965Sjdp if (target->sy_previous != NULL) 84933965Sjdp { 85033965Sjdp target->sy_previous->sy_next = addme; 85133965Sjdp } 85233965Sjdp else 85333965Sjdp { 85433965Sjdp know (*rootPP == target); 85533965Sjdp *rootPP = addme; 85677298Sobrien } /* if not first */ 85733965Sjdp 85833965Sjdp addme->sy_previous = target->sy_previous; 85933965Sjdp target->sy_previous = addme; 86033965Sjdp addme->sy_next = target; 86133965Sjdp 86233965Sjdp debug_verify_symchain (*rootPP, *lastPP); 86333965Sjdp} 86433965Sjdp 86577298Sobrienvoid 866130561Sobrienverify_symbol_chain (symbolS *rootP, symbolS *lastP) 86733965Sjdp{ 86833965Sjdp symbolS *symbolP = rootP; 86933965Sjdp 87033965Sjdp if (symbolP == NULL) 87133965Sjdp return; 87233965Sjdp 87333965Sjdp for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) 87433965Sjdp { 87560484Sobrien assert (symbolP->bsym != NULL); 87633965Sjdp assert (symbolP->sy_next->sy_previous == symbolP); 87733965Sjdp } 87833965Sjdp 87933965Sjdp assert (lastP == symbolP); 88033965Sjdp} 88133965Sjdp 882218822Sdim#ifdef OBJ_COMPLEX_RELC 883218822Sdim 884218822Sdimstatic int 885218822Sdimuse_complex_relocs_for (symbolS * symp) 88633965Sjdp{ 887218822Sdim switch (symp->sy_value.X_op) 888218822Sdim { 889218822Sdim case O_constant: 890218822Sdim return 0; 891218822Sdim 892218822Sdim case O_symbol: 893218822Sdim case O_symbol_rva: 894218822Sdim case O_uminus: 895218822Sdim case O_bit_not: 896218822Sdim case O_logical_not: 897218822Sdim if ( (S_IS_COMMON (symp->sy_value.X_add_symbol) 898218822Sdim || S_IS_LOCAL (symp->sy_value.X_add_symbol)) 899218822Sdim && 900218822Sdim (S_IS_DEFINED (symp->sy_value.X_add_symbol) 901218822Sdim && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section)) 902218822Sdim return 0; 903218822Sdim break; 904218822Sdim 905218822Sdim case O_multiply: 906218822Sdim case O_divide: 907218822Sdim case O_modulus: 908218822Sdim case O_left_shift: 909218822Sdim case O_right_shift: 910218822Sdim case O_bit_inclusive_or: 911218822Sdim case O_bit_or_not: 912218822Sdim case O_bit_exclusive_or: 913218822Sdim case O_bit_and: 914218822Sdim case O_add: 915218822Sdim case O_subtract: 916218822Sdim case O_eq: 917218822Sdim case O_ne: 918218822Sdim case O_lt: 919218822Sdim case O_le: 920218822Sdim case O_ge: 921218822Sdim case O_gt: 922218822Sdim case O_logical_and: 923218822Sdim case O_logical_or: 924218822Sdim 925218822Sdim if ( (S_IS_COMMON (symp->sy_value.X_add_symbol) 926218822Sdim || S_IS_LOCAL (symp->sy_value.X_add_symbol)) 927218822Sdim && 928218822Sdim (S_IS_COMMON (symp->sy_value.X_op_symbol) 929218822Sdim || S_IS_LOCAL (symp->sy_value.X_op_symbol)) 930218822Sdim 931218822Sdim && S_IS_DEFINED (symp->sy_value.X_add_symbol) 932218822Sdim && S_IS_DEFINED (symp->sy_value.X_op_symbol) 933218822Sdim && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section 934218822Sdim && S_GET_SEGMENT (symp->sy_value.X_op_symbol) != expr_section) 935218822Sdim return 0; 936218822Sdim break; 937218822Sdim 938218822Sdim default: 939218822Sdim break; 940218822Sdim } 941218822Sdim return 1; 942218822Sdim} 94333965Sjdp#endif 94433965Sjdp 945130561Sobrienstatic void 946130561Sobrienreport_op_error (symbolS *symp, symbolS *left, symbolS *right) 947130561Sobrien{ 948130561Sobrien char *file; 949130561Sobrien unsigned int line; 950130561Sobrien segT seg_left = S_GET_SEGMENT (left); 951130561Sobrien segT seg_right = right ? S_GET_SEGMENT (right) : 0; 952130561Sobrien 953130561Sobrien if (expr_symbol_where (symp, &file, &line)) 954130561Sobrien { 955130561Sobrien if (seg_left == undefined_section) 956130561Sobrien as_bad_where (file, line, 957130561Sobrien _("undefined symbol `%s' in operation"), 958130561Sobrien S_GET_NAME (left)); 959130561Sobrien if (seg_right == undefined_section) 960130561Sobrien as_bad_where (file, line, 961130561Sobrien _("undefined symbol `%s' in operation"), 962130561Sobrien S_GET_NAME (right)); 963130561Sobrien if (seg_left != undefined_section 964130561Sobrien && seg_right != undefined_section) 965130561Sobrien { 966130561Sobrien if (right) 967130561Sobrien as_bad_where (file, line, 968130561Sobrien _("invalid sections for operation on `%s' and `%s'"), 969130561Sobrien S_GET_NAME (left), S_GET_NAME (right)); 970130561Sobrien else 971130561Sobrien as_bad_where (file, line, 972130561Sobrien _("invalid section for operation on `%s'"), 973130561Sobrien S_GET_NAME (left)); 974130561Sobrien } 975130561Sobrien 976130561Sobrien } 977130561Sobrien else 978130561Sobrien { 979130561Sobrien if (seg_left == undefined_section) 980130561Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 981130561Sobrien S_GET_NAME (left), S_GET_NAME (symp)); 982130561Sobrien if (seg_right == undefined_section) 983130561Sobrien as_bad (_("undefined symbol `%s' in operation setting `%s'"), 984130561Sobrien S_GET_NAME (right), S_GET_NAME (symp)); 985130561Sobrien if (seg_left != undefined_section 986130561Sobrien && seg_right != undefined_section) 987130561Sobrien { 988130561Sobrien if (right) 989218822Sdim as_bad (_("invalid sections for operation on `%s' and `%s' setting `%s'"), 990218822Sdim S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp)); 991130561Sobrien else 992218822Sdim as_bad (_("invalid section for operation on `%s' setting `%s'"), 993218822Sdim S_GET_NAME (left), S_GET_NAME (symp)); 994130561Sobrien } 995130561Sobrien } 996130561Sobrien} 997130561Sobrien 99833965Sjdp/* Resolve the value of a symbol. This is called during the final 99933965Sjdp pass over the symbol table to resolve any symbols with complex 100033965Sjdp values. */ 100133965Sjdp 100238889SjdpvalueT 1003130561Sobrienresolve_symbol_value (symbolS *symp) 100433965Sjdp{ 100533965Sjdp int resolved; 1006104834Sobrien valueT final_val = 0; 100738889Sjdp segT final_seg; 100833965Sjdp 100960484Sobrien if (LOCAL_SYMBOL_CHECK (symp)) 101060484Sobrien { 101160484Sobrien struct local_symbol *locsym = (struct local_symbol *) symp; 101260484Sobrien 101389857Sobrien final_val = locsym->lsy_value; 101460484Sobrien if (local_symbol_resolved_p (locsym)) 101589857Sobrien return final_val; 101660484Sobrien 101789857Sobrien final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE; 101860484Sobrien 101989857Sobrien if (finalize_syms) 102060484Sobrien { 102189857Sobrien locsym->lsy_value = final_val; 102260484Sobrien local_symbol_mark_resolved (locsym); 102360484Sobrien } 102460484Sobrien 102560484Sobrien return final_val; 102660484Sobrien } 102760484Sobrien 102833965Sjdp if (symp->sy_resolved) 102938889Sjdp { 103038889Sjdp if (symp->sy_value.X_op == O_constant) 103138889Sjdp return (valueT) symp->sy_value.X_add_number; 103238889Sjdp else 103338889Sjdp return 0; 103438889Sjdp } 103533965Sjdp 103633965Sjdp resolved = 0; 103738889Sjdp final_seg = S_GET_SEGMENT (symp); 103833965Sjdp 103933965Sjdp if (symp->sy_resolving) 104033965Sjdp { 104189857Sobrien if (finalize_syms) 104289857Sobrien as_bad (_("symbol definition loop encountered at `%s'"), 104377298Sobrien S_GET_NAME (symp)); 104438889Sjdp final_val = 0; 104533965Sjdp resolved = 1; 104633965Sjdp } 1047218822Sdim#ifdef OBJ_COMPLEX_RELC 1048218822Sdim else if (final_seg == expr_section 1049218822Sdim && use_complex_relocs_for (symp)) 1050218822Sdim { 1051218822Sdim symbolS * relc_symbol = NULL; 1052218822Sdim char * relc_symbol_name = NULL; 1053218822Sdim 1054218822Sdim relc_symbol_name = symbol_relc_make_expr (& symp->sy_value); 1055218822Sdim 1056218822Sdim /* For debugging, print out conversion input & output. */ 1057218822Sdim#ifdef DEBUG_SYMS 1058218822Sdim print_expr (& symp->sy_value); 1059218822Sdim if (relc_symbol_name) 1060218822Sdim fprintf (stderr, "-> relc symbol: %s\n", relc_symbol_name); 1061218822Sdim#endif 1062218822Sdim 1063218822Sdim if (relc_symbol_name != NULL) 1064218822Sdim relc_symbol = symbol_new (relc_symbol_name, undefined_section, 1065218822Sdim 0, & zero_address_frag); 1066218822Sdim 1067218822Sdim if (relc_symbol == NULL) 1068218822Sdim { 1069218822Sdim as_bad (_("cannot convert expression symbol %s to complex relocation"), 1070218822Sdim S_GET_NAME (symp)); 1071218822Sdim resolved = 0; 1072218822Sdim } 1073218822Sdim else 1074218822Sdim { 1075218822Sdim symbol_table_insert (relc_symbol); 1076218822Sdim 1077218822Sdim /* S_CLEAR_EXTERNAL (relc_symbol); */ 1078218822Sdim if (symp->bsym->flags & BSF_SRELC) 1079218822Sdim relc_symbol->bsym->flags |= BSF_SRELC; 1080218822Sdim else 1081218822Sdim relc_symbol->bsym->flags |= BSF_RELC; 1082218822Sdim /* symp->bsym->flags |= BSF_RELC; */ 1083218822Sdim copy_symbol_attributes (symp, relc_symbol); 1084218822Sdim symp->sy_value.X_op = O_symbol; 1085218822Sdim symp->sy_value.X_add_symbol = relc_symbol; 1086218822Sdim symp->sy_value.X_add_number = 0; 1087218822Sdim resolved = 1; 1088218822Sdim } 1089218822Sdim 1090218822Sdim final_seg = undefined_section; 1091218822Sdim goto exit_dont_set_value; 1092218822Sdim } 1093218822Sdim#endif 109433965Sjdp else 109533965Sjdp { 109638889Sjdp symbolS *add_symbol, *op_symbol; 109738889Sjdp offsetT left, right; 109833965Sjdp segT seg_left, seg_right; 109938889Sjdp operatorT op; 1100218822Sdim int move_seg_ok; 110133965Sjdp 110233965Sjdp symp->sy_resolving = 1; 110333965Sjdp 110438889Sjdp /* Help out with CSE. */ 110538889Sjdp add_symbol = symp->sy_value.X_add_symbol; 110638889Sjdp op_symbol = symp->sy_value.X_op_symbol; 110738889Sjdp final_val = symp->sy_value.X_add_number; 110838889Sjdp op = symp->sy_value.X_op; 110938889Sjdp 111038889Sjdp switch (op) 111133965Sjdp { 111238889Sjdp default: 111338889Sjdp BAD_CASE (op); 111438889Sjdp break; 111533965Sjdp 111633965Sjdp case O_absent: 111738889Sjdp final_val = 0; 111833965Sjdp /* Fall through. */ 111938889Sjdp 112033965Sjdp case O_constant: 112160484Sobrien final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; 112238889Sjdp if (final_seg == expr_section) 112338889Sjdp final_seg = absolute_section; 1124218822Sdim /* Fall through. */ 1125218822Sdim 1126218822Sdim case O_register: 112733965Sjdp resolved = 1; 112833965Sjdp break; 112933965Sjdp 113033965Sjdp case O_symbol: 113138889Sjdp case O_symbol_rva: 113289857Sobrien left = resolve_symbol_value (add_symbol); 113389857Sobrien seg_left = S_GET_SEGMENT (add_symbol); 113489857Sobrien if (finalize_syms) 113589857Sobrien symp->sy_value.X_op_symbol = NULL; 113689857Sobrien 113738889Sjdp do_symbol: 1138218822Sdim if (S_IS_WEAKREFR (symp)) 1139218822Sdim { 1140218822Sdim assert (final_val == 0); 1141218822Sdim if (S_IS_WEAKREFR (add_symbol)) 1142218822Sdim { 1143218822Sdim assert (add_symbol->sy_value.X_op == O_symbol 1144218822Sdim && add_symbol->sy_value.X_add_number == 0); 1145218822Sdim add_symbol = add_symbol->sy_value.X_add_symbol; 1146218822Sdim assert (! S_IS_WEAKREFR (add_symbol)); 1147218822Sdim symp->sy_value.X_add_symbol = add_symbol; 1148218822Sdim } 1149218822Sdim } 1150218822Sdim 115133965Sjdp if (symp->sy_mri_common) 115233965Sjdp { 115333965Sjdp /* This is a symbol inside an MRI common section. The 115489857Sobrien relocation routines are going to handle it specially. 115589857Sobrien Don't change the value. */ 115660484Sobrien resolved = symbol_resolved_p (add_symbol); 115733965Sjdp break; 115833965Sjdp } 115933965Sjdp 116089857Sobrien if (finalize_syms && final_val == 0) 116160484Sobrien { 116260484Sobrien if (LOCAL_SYMBOL_CHECK (add_symbol)) 116360484Sobrien add_symbol = local_symbol_convert ((struct local_symbol *) 116460484Sobrien add_symbol); 116560484Sobrien copy_symbol_attributes (symp, add_symbol); 116660484Sobrien } 116733965Sjdp 116889857Sobrien /* If we have equated this symbol to an undefined or common 116989857Sobrien symbol, keep X_op set to O_symbol, and don't change 117089857Sobrien X_add_number. This permits the routine which writes out 117189857Sobrien relocation to detect this case, and convert the 117289857Sobrien relocation to be against the symbol to which this symbol 117389857Sobrien is equated. */ 1174218822Sdim if (! S_IS_DEFINED (add_symbol) 1175218822Sdim#if defined (OBJ_COFF) && defined (TE_PE) 1176218822Sdim || S_IS_WEAK (add_symbol) 1177218822Sdim#endif 1178218822Sdim || S_IS_COMMON (add_symbol)) 117933965Sjdp { 118089857Sobrien if (finalize_syms) 118138889Sjdp { 118238889Sjdp symp->sy_value.X_op = O_symbol; 118360484Sobrien symp->sy_value.X_add_symbol = add_symbol; 118438889Sjdp symp->sy_value.X_add_number = final_val; 118589857Sobrien /* Use X_op_symbol as a flag. */ 118689857Sobrien symp->sy_value.X_op_symbol = add_symbol; 118789857Sobrien final_seg = seg_left; 118838889Sjdp } 118938889Sjdp final_val = 0; 119060484Sobrien resolved = symbol_resolved_p (add_symbol); 119189857Sobrien symp->sy_resolving = 0; 119238889Sjdp goto exit_dont_set_value; 119333965Sjdp } 1194218822Sdim else if (finalize_syms 1195218822Sdim && ((final_seg == expr_section && seg_left != expr_section) 1196218822Sdim || symbol_shadow_p (symp))) 119789857Sobrien { 119889857Sobrien /* If the symbol is an expression symbol, do similarly 119989857Sobrien as for undefined and common syms above. Handles 120089857Sobrien "sym +/- expr" where "expr" cannot be evaluated 120189857Sobrien immediately, and we want relocations to be against 120289857Sobrien "sym", eg. because it is weak. */ 120389857Sobrien symp->sy_value.X_op = O_symbol; 120489857Sobrien symp->sy_value.X_add_symbol = add_symbol; 120589857Sobrien symp->sy_value.X_add_number = final_val; 120689857Sobrien symp->sy_value.X_op_symbol = add_symbol; 120789857Sobrien final_seg = seg_left; 120889857Sobrien final_val += symp->sy_frag->fr_address + left; 120989857Sobrien resolved = symbol_resolved_p (add_symbol); 121089857Sobrien symp->sy_resolving = 0; 121189857Sobrien goto exit_dont_set_value; 121289857Sobrien } 121333965Sjdp else 121433965Sjdp { 121538889Sjdp final_val += symp->sy_frag->fr_address + left; 121638889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 121789857Sobrien final_seg = seg_left; 121833965Sjdp } 121933965Sjdp 122060484Sobrien resolved = symbol_resolved_p (add_symbol); 1221218822Sdim if (S_IS_WEAKREFR (symp)) 1222218822Sdim goto exit_dont_set_value; 122333965Sjdp break; 122433965Sjdp 122533965Sjdp case O_uminus: 122633965Sjdp case O_bit_not: 122733965Sjdp case O_logical_not: 122889857Sobrien left = resolve_symbol_value (add_symbol); 122999461Sobrien seg_left = S_GET_SEGMENT (add_symbol); 123038889Sjdp 1231130561Sobrien /* By reducing these to the relevant dyadic operator, we get 1232130561Sobrien !S -> S == 0 permitted on anything, 1233130561Sobrien -S -> 0 - S only permitted on absolute 1234130561Sobrien ~S -> S ^ ~0 only permitted on absolute */ 1235130561Sobrien if (op != O_logical_not && seg_left != absolute_section 1236130561Sobrien && finalize_syms) 1237130561Sobrien report_op_error (symp, add_symbol, NULL); 1238130561Sobrien 1239130561Sobrien if (final_seg == expr_section || final_seg == undefined_section) 1240130561Sobrien final_seg = absolute_section; 1241130561Sobrien 124238889Sjdp if (op == O_uminus) 124338889Sjdp left = -left; 124438889Sjdp else if (op == O_logical_not) 124538889Sjdp left = !left; 124633965Sjdp else 124738889Sjdp left = ~left; 124838889Sjdp 124938889Sjdp final_val += left + symp->sy_frag->fr_address; 125038889Sjdp 125160484Sobrien resolved = symbol_resolved_p (add_symbol); 125233965Sjdp break; 125333965Sjdp 125433965Sjdp case O_multiply: 125533965Sjdp case O_divide: 125633965Sjdp case O_modulus: 125733965Sjdp case O_left_shift: 125833965Sjdp case O_right_shift: 125933965Sjdp case O_bit_inclusive_or: 126033965Sjdp case O_bit_or_not: 126133965Sjdp case O_bit_exclusive_or: 126233965Sjdp case O_bit_and: 126333965Sjdp case O_add: 126433965Sjdp case O_subtract: 126533965Sjdp case O_eq: 126633965Sjdp case O_ne: 126733965Sjdp case O_lt: 126833965Sjdp case O_le: 126933965Sjdp case O_ge: 127033965Sjdp case O_gt: 127133965Sjdp case O_logical_and: 127233965Sjdp case O_logical_or: 127389857Sobrien left = resolve_symbol_value (add_symbol); 127489857Sobrien right = resolve_symbol_value (op_symbol); 127538889Sjdp seg_left = S_GET_SEGMENT (add_symbol); 127638889Sjdp seg_right = S_GET_SEGMENT (op_symbol); 127733965Sjdp 127838889Sjdp /* Simplify addition or subtraction of a constant by folding the 127938889Sjdp constant into X_add_number. */ 128089857Sobrien if (op == O_add) 128138889Sjdp { 128238889Sjdp if (seg_right == absolute_section) 128338889Sjdp { 128489857Sobrien final_val += right; 128538889Sjdp goto do_symbol; 128638889Sjdp } 128789857Sobrien else if (seg_left == absolute_section) 128838889Sjdp { 128938889Sjdp final_val += left; 129038889Sjdp add_symbol = op_symbol; 129138889Sjdp left = right; 129289857Sobrien seg_left = seg_right; 129338889Sjdp goto do_symbol; 129438889Sjdp } 129538889Sjdp } 129689857Sobrien else if (op == O_subtract) 129789857Sobrien { 129889857Sobrien if (seg_right == absolute_section) 129989857Sobrien { 130089857Sobrien final_val -= right; 130189857Sobrien goto do_symbol; 130289857Sobrien } 130389857Sobrien } 130438889Sjdp 1305218822Sdim move_seg_ok = 1; 130689857Sobrien /* Equality and non-equality tests are permitted on anything. 130789857Sobrien Subtraction, and other comparison operators are permitted if 130889857Sobrien both operands are in the same section. Otherwise, both 130989857Sobrien operands must be absolute. We already handled the case of 131089857Sobrien addition or subtraction of a constant above. This will 131189857Sobrien probably need to be changed for an object file format which 1312218822Sdim supports arbitrary expressions, such as IEEE-695. */ 1313218822Sdim if (!(seg_left == absolute_section 1314130561Sobrien && seg_right == absolute_section) 1315130561Sobrien && !(op == O_eq || op == O_ne) 1316130561Sobrien && !((op == O_subtract 1317130561Sobrien || op == O_lt || op == O_le || op == O_ge || op == O_gt) 1318130561Sobrien && seg_left == seg_right 1319130561Sobrien && (seg_left != undefined_section 1320130561Sobrien || add_symbol == op_symbol))) 1321218822Sdim { 1322218822Sdim /* Don't emit messages unless we're finalizing the symbol value, 1323218822Sdim otherwise we may get the same message multiple times. */ 1324218822Sdim if (finalize_syms) 1325218822Sdim report_op_error (symp, add_symbol, op_symbol); 1326218822Sdim /* However do not move the symbol into the absolute section 1327218822Sdim if it cannot currently be resolved - this would confuse 1328218822Sdim other parts of the assembler into believing that the 1329218822Sdim expression had been evaluated to zero. */ 1330218822Sdim else 1331218822Sdim move_seg_ok = 0; 1332218822Sdim } 133333965Sjdp 1334218822Sdim if (move_seg_ok 1335218822Sdim && (final_seg == expr_section || final_seg == undefined_section)) 1336130561Sobrien final_seg = absolute_section; 133733965Sjdp 133838889Sjdp /* Check for division by zero. */ 133938889Sjdp if ((op == O_divide || op == O_modulus) && right == 0) 134038889Sjdp { 134138889Sjdp /* If seg_right is not absolute_section, then we've 134289857Sobrien already issued a warning about using a bad symbol. */ 134389857Sobrien if (seg_right == absolute_section && finalize_syms) 134438889Sjdp { 134538889Sjdp char *file; 134638889Sjdp unsigned int line; 134738889Sjdp 134838889Sjdp if (expr_symbol_where (symp, &file, &line)) 134960484Sobrien as_bad_where (file, line, _("division by zero")); 135038889Sjdp else 135189857Sobrien as_bad (_("division by zero when setting `%s'"), 135238889Sjdp S_GET_NAME (symp)); 135338889Sjdp } 135438889Sjdp 135538889Sjdp right = 1; 135638889Sjdp } 135738889Sjdp 135833965Sjdp switch (symp->sy_value.X_op) 135933965Sjdp { 136038889Sjdp case O_multiply: left *= right; break; 136138889Sjdp case O_divide: left /= right; break; 136238889Sjdp case O_modulus: left %= right; break; 136338889Sjdp case O_left_shift: left <<= right; break; 136438889Sjdp case O_right_shift: left >>= right; break; 136538889Sjdp case O_bit_inclusive_or: left |= right; break; 136638889Sjdp case O_bit_or_not: left |= ~right; break; 136738889Sjdp case O_bit_exclusive_or: left ^= right; break; 136838889Sjdp case O_bit_and: left &= right; break; 136938889Sjdp case O_add: left += right; break; 137038889Sjdp case O_subtract: left -= right; break; 137189857Sobrien case O_eq: 137289857Sobrien case O_ne: 137389857Sobrien left = (left == right && seg_left == seg_right 137489857Sobrien && (seg_left != undefined_section 137589857Sobrien || add_symbol == op_symbol) 137689857Sobrien ? ~ (offsetT) 0 : 0); 137789857Sobrien if (symp->sy_value.X_op == O_ne) 137889857Sobrien left = ~left; 137989857Sobrien break; 138038889Sjdp case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; 138138889Sjdp case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; 138238889Sjdp case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; 138338889Sjdp case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; 138438889Sjdp case O_logical_and: left = left && right; break; 138538889Sjdp case O_logical_or: left = left || right; break; 138638889Sjdp default: abort (); 138733965Sjdp } 138838889Sjdp 138938889Sjdp final_val += symp->sy_frag->fr_address + left; 139038889Sjdp if (final_seg == expr_section || final_seg == undefined_section) 139199461Sobrien { 139299461Sobrien if (seg_left == undefined_section 139399461Sobrien || seg_right == undefined_section) 139499461Sobrien final_seg = undefined_section; 139599461Sobrien else if (seg_left == absolute_section) 139699461Sobrien final_seg = seg_right; 139799461Sobrien else 139899461Sobrien final_seg = seg_left; 139999461Sobrien } 140060484Sobrien resolved = (symbol_resolved_p (add_symbol) 140160484Sobrien && symbol_resolved_p (op_symbol)); 140277298Sobrien break; 140333965Sjdp 140433965Sjdp case O_big: 140533965Sjdp case O_illegal: 140633965Sjdp /* Give an error (below) if not in expr_section. We don't 140733965Sjdp want to worry about expr_section symbols, because they 140833965Sjdp are fictional (they are created as part of expression 140933965Sjdp resolution), and any problems may not actually mean 141033965Sjdp anything. */ 141133965Sjdp break; 141233965Sjdp } 141338889Sjdp 141438889Sjdp symp->sy_resolving = 0; 141533965Sjdp } 141633965Sjdp 141789857Sobrien if (finalize_syms) 141889857Sobrien S_SET_VALUE (symp, final_val); 141938889Sjdp 142089857Sobrienexit_dont_set_value: 142189857Sobrien /* Always set the segment, even if not finalizing the value. 142289857Sobrien The segment is used to determine whether a symbol is defined. */ 142389857Sobrien S_SET_SEGMENT (symp, final_seg); 142438889Sjdp 142533965Sjdp /* Don't worry if we can't resolve an expr_section symbol. */ 142689857Sobrien if (finalize_syms) 142733965Sjdp { 142838889Sjdp if (resolved) 142938889Sjdp symp->sy_resolved = 1; 143038889Sjdp else if (S_GET_SEGMENT (symp) != expr_section) 143138889Sjdp { 143289857Sobrien as_bad (_("can't resolve value for symbol `%s'"), 143377298Sobrien S_GET_NAME (symp)); 143438889Sjdp symp->sy_resolved = 1; 143538889Sjdp } 143633965Sjdp } 143738889Sjdp 143838889Sjdp return final_val; 143933965Sjdp} 144033965Sjdp 1441130561Sobrienstatic void resolve_local_symbol (const char *, PTR); 144260484Sobrien 144360484Sobrien/* A static function passed to hash_traverse. */ 144460484Sobrien 144560484Sobrienstatic void 1446130561Sobrienresolve_local_symbol (const char *key ATTRIBUTE_UNUSED, PTR value) 144760484Sobrien{ 144860484Sobrien if (value != NULL) 144989857Sobrien resolve_symbol_value (value); 145060484Sobrien} 145160484Sobrien 145260484Sobrien/* Resolve all local symbols. */ 145360484Sobrien 145460484Sobrienvoid 1455130561Sobrienresolve_local_symbol_values (void) 145660484Sobrien{ 145760484Sobrien hash_traverse (local_hash, resolve_local_symbol); 145860484Sobrien} 145960484Sobrien 1460218822Sdim/* Obtain the current value of a symbol without changing any 1461218822Sdim sub-expressions used. */ 1462218822Sdim 1463218822Sdimint 1464218822Sdimsnapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP) 1465218822Sdim{ 1466218822Sdim symbolS *symbolP = *symbolPP; 1467218822Sdim 1468218822Sdim if (LOCAL_SYMBOL_CHECK (symbolP)) 1469218822Sdim { 1470218822Sdim struct local_symbol *locsym = (struct local_symbol *) symbolP; 1471218822Sdim 1472218822Sdim *valueP = locsym->lsy_value; 1473218822Sdim *segP = locsym->lsy_section; 1474218822Sdim *fragPP = local_symbol_get_frag (locsym); 1475218822Sdim } 1476218822Sdim else 1477218822Sdim { 1478218822Sdim expressionS expr = symbolP->sy_value; 1479218822Sdim 1480218822Sdim if (!symbolP->sy_resolved && expr.X_op != O_illegal) 1481218822Sdim { 1482218822Sdim int resolved; 1483218822Sdim 1484218822Sdim if (symbolP->sy_resolving) 1485218822Sdim return 0; 1486218822Sdim symbolP->sy_resolving = 1; 1487218822Sdim resolved = resolve_expression (&expr); 1488218822Sdim symbolP->sy_resolving = 0; 1489218822Sdim if (!resolved) 1490218822Sdim return 0; 1491218822Sdim 1492218822Sdim switch (expr.X_op) 1493218822Sdim { 1494218822Sdim case O_constant: 1495218822Sdim case O_register: 1496218822Sdim if (!symbol_equated_p (symbolP)) 1497218822Sdim break; 1498218822Sdim /* Fall thru. */ 1499218822Sdim case O_symbol: 1500218822Sdim case O_symbol_rva: 1501218822Sdim symbolP = expr.X_add_symbol; 1502218822Sdim break; 1503218822Sdim default: 1504218822Sdim return 0; 1505218822Sdim } 1506218822Sdim } 1507218822Sdim 1508218822Sdim /* Never change a defined symbol. */ 1509218822Sdim if (symbolP->bsym->section == undefined_section 1510218822Sdim || symbolP->bsym->section == expr_section) 1511218822Sdim *symbolPP = symbolP; 1512218822Sdim *valueP = expr.X_add_number; 1513218822Sdim *segP = symbolP->bsym->section; 1514218822Sdim *fragPP = symbolP->sy_frag; 1515218822Sdim 1516218822Sdim if (*segP == expr_section) 1517218822Sdim switch (expr.X_op) 1518218822Sdim { 1519218822Sdim case O_constant: *segP = absolute_section; break; 1520218822Sdim case O_register: *segP = reg_section; break; 1521218822Sdim default: break; 1522218822Sdim } 1523218822Sdim } 1524218822Sdim 1525218822Sdim return 1; 1526218822Sdim} 1527218822Sdim 152833965Sjdp/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". 152933965Sjdp They are *really* local. That is, they go out of scope whenever we see a 153033965Sjdp label that isn't local. Also, like fb labels, there can be multiple 153133965Sjdp instances of a dollar label. Therefor, we name encode each instance with 153233965Sjdp the instance number, keep a list of defined symbols separate from the real 153333965Sjdp symbol table, and we treat these buggers as a sparse array. */ 153433965Sjdp 153533965Sjdpstatic long *dollar_labels; 153633965Sjdpstatic long *dollar_label_instances; 153733965Sjdpstatic char *dollar_label_defines; 153838889Sjdpstatic unsigned long dollar_label_count; 153933965Sjdpstatic unsigned long dollar_label_max; 154033965Sjdp 154177298Sobrienint 1542130561Sobriendollar_label_defined (long label) 154333965Sjdp{ 154433965Sjdp long *i; 154533965Sjdp 154633965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 154733965Sjdp 154833965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 154933965Sjdp if (*i == label) 155033965Sjdp return dollar_label_defines[i - dollar_labels]; 155133965Sjdp 155277298Sobrien /* If we get here, label isn't defined. */ 155333965Sjdp return 0; 155477298Sobrien} 155533965Sjdp 155633965Sjdpstatic long 1557130561Sobriendollar_label_instance (long label) 155833965Sjdp{ 155933965Sjdp long *i; 156033965Sjdp 156133965Sjdp know ((dollar_labels != NULL) || (dollar_label_count == 0)); 156233965Sjdp 156333965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 156433965Sjdp if (*i == label) 156533965Sjdp return (dollar_label_instances[i - dollar_labels]); 156633965Sjdp 156777298Sobrien /* If we get here, we haven't seen the label before. 156877298Sobrien Therefore its instance count is zero. */ 156933965Sjdp return 0; 157033965Sjdp} 157133965Sjdp 157277298Sobrienvoid 1573130561Sobriendollar_label_clear (void) 157433965Sjdp{ 157533965Sjdp memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count); 157633965Sjdp} 157733965Sjdp 157833965Sjdp#define DOLLAR_LABEL_BUMP_BY 10 157933965Sjdp 158077298Sobrienvoid 1581130561Sobriendefine_dollar_label (long label) 158233965Sjdp{ 158333965Sjdp long *i; 158433965Sjdp 158533965Sjdp for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) 158633965Sjdp if (*i == label) 158733965Sjdp { 158833965Sjdp ++dollar_label_instances[i - dollar_labels]; 158933965Sjdp dollar_label_defines[i - dollar_labels] = 1; 159033965Sjdp return; 159133965Sjdp } 159233965Sjdp 159377298Sobrien /* If we get to here, we don't have label listed yet. */ 159433965Sjdp 159533965Sjdp if (dollar_labels == NULL) 159633965Sjdp { 159733965Sjdp dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 159833965Sjdp dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long)); 159933965Sjdp dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY); 160033965Sjdp dollar_label_max = DOLLAR_LABEL_BUMP_BY; 160133965Sjdp dollar_label_count = 0; 160233965Sjdp } 160333965Sjdp else if (dollar_label_count == dollar_label_max) 160433965Sjdp { 160533965Sjdp dollar_label_max += DOLLAR_LABEL_BUMP_BY; 160633965Sjdp dollar_labels = (long *) xrealloc ((char *) dollar_labels, 160733965Sjdp dollar_label_max * sizeof (long)); 160833965Sjdp dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances, 160933965Sjdp dollar_label_max * sizeof (long)); 161033965Sjdp dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max); 161177298Sobrien } /* if we needed to grow */ 161233965Sjdp 161333965Sjdp dollar_labels[dollar_label_count] = label; 161433965Sjdp dollar_label_instances[dollar_label_count] = 1; 161533965Sjdp dollar_label_defines[dollar_label_count] = 1; 161633965Sjdp ++dollar_label_count; 161733965Sjdp} 161833965Sjdp 161977298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 162033965Sjdp 162177298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Am" 162277298Sobrien where n is the label number and m is the instance number. "L" makes 162377298Sobrien it a label discarded unless debugging and "^A"('\1') ensures no 162477298Sobrien ordinary symbol SHOULD get the same name as a local label 162577298Sobrien symbol. The first "4:" is "L4^A1" - the m numbers begin at 1. 162677298Sobrien 162777298Sobrien fb labels get the same treatment, except that ^B is used in place 162877298Sobrien of ^A. */ 162977298Sobrien 163077298Sobrienchar * /* Return local label name. */ 1631130561Sobriendollar_label_name (register long n, /* we just saw "n$:" : n a number. */ 1632130561Sobrien register int augend /* 0 for current instance, 1 for new instance. */) 163333965Sjdp{ 163433965Sjdp long i; 163577298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 163633965Sjdp static char symbol_name_build[24]; 163733965Sjdp register char *p; 163833965Sjdp register char *q; 163977298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 164033965Sjdp 164133965Sjdp know (n >= 0); 164233965Sjdp know (augend == 0 || augend == 1); 164333965Sjdp p = symbol_name_build; 164460484Sobrien#ifdef LOCAL_LABEL_PREFIX 164560484Sobrien *p++ = LOCAL_LABEL_PREFIX; 164660484Sobrien#endif 164733965Sjdp *p++ = 'L'; 164833965Sjdp 164977298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 165077298Sobrien /* Label number. */ 165133965Sjdp q = symbol_name_temporary; 165233965Sjdp for (*q++ = 0, i = n; i; ++q) 165333965Sjdp { 165433965Sjdp *q = i % 10 + '0'; 165533965Sjdp i /= 10; 165633965Sjdp } 165733965Sjdp while ((*p = *--q) != '\0') 165833965Sjdp ++p; 165933965Sjdp 166077298Sobrien *p++ = DOLLAR_LABEL_CHAR; /* ^A */ 166133965Sjdp 166277298Sobrien /* Instance number. */ 166333965Sjdp q = symbol_name_temporary; 166433965Sjdp for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q) 166533965Sjdp { 166633965Sjdp *q = i % 10 + '0'; 166733965Sjdp i /= 10; 166833965Sjdp } 1669257360Ssbruno while ((*p++ = *--q) != '\0') 1670257360Ssbruno ;; 167133965Sjdp 167277298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 167333965Sjdp return symbol_name_build; 167433965Sjdp} 167533965Sjdp 1676130561Sobrien/* Somebody else's idea of local labels. They are made by "n:" where n 167777298Sobrien is any decimal digit. Refer to them with 167877298Sobrien "nb" for previous (backward) n: 167977298Sobrien or "nf" for next (forward) n:. 168033965Sjdp 168177298Sobrien We do a little better and let n be any number, not just a single digit, but 168277298Sobrien since the other guy's assembler only does ten, we treat the first ten 168377298Sobrien specially. 168477298Sobrien 168577298Sobrien Like someone else's assembler, we have one set of local label counters for 168677298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 168777298Sobrien implies that one can refer to a label in another segment, and indeed some 168877298Sobrien crufty compilers have done just that. 168977298Sobrien 169077298Sobrien Since there could be a LOT of these things, treat them as a sparse 169177298Sobrien array. */ 169277298Sobrien 169333965Sjdp#define FB_LABEL_SPECIAL (10) 169433965Sjdp 169533965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 169633965Sjdpstatic long *fb_labels; 169733965Sjdpstatic long *fb_label_instances; 169833965Sjdpstatic long fb_label_count; 169933965Sjdpstatic long fb_label_max; 170033965Sjdp 170177298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 170233965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 170333965Sjdp 170477298Sobrienstatic void 1705130561Sobrienfb_label_init (void) 170633965Sjdp{ 170733965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 170877298Sobrien} 170933965Sjdp 171077298Sobrien/* Add one to the instance number of this fb label. */ 171177298Sobrien 171277298Sobrienvoid 1713130561Sobrienfb_label_instance_inc (long label) 171433965Sjdp{ 171533965Sjdp long *i; 171633965Sjdp 171733965Sjdp if (label < FB_LABEL_SPECIAL) 171833965Sjdp { 171933965Sjdp ++fb_low_counter[label]; 172033965Sjdp return; 172133965Sjdp } 172233965Sjdp 172333965Sjdp if (fb_labels != NULL) 172433965Sjdp { 172533965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 172633965Sjdp i < fb_labels + fb_label_count; ++i) 172733965Sjdp { 172833965Sjdp if (*i == label) 172933965Sjdp { 173033965Sjdp ++fb_label_instances[i - fb_labels]; 173133965Sjdp return; 173277298Sobrien } /* if we find it */ 173377298Sobrien } /* for each existing label */ 173433965Sjdp } 173533965Sjdp 173677298Sobrien /* If we get to here, we don't have label listed yet. */ 173733965Sjdp 173833965Sjdp if (fb_labels == NULL) 173933965Sjdp { 174033965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 174133965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 174233965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 174333965Sjdp fb_label_count = FB_LABEL_SPECIAL; 174433965Sjdp 174533965Sjdp } 174633965Sjdp else if (fb_label_count == fb_label_max) 174733965Sjdp { 174833965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 174933965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 175033965Sjdp fb_label_max * sizeof (long)); 175133965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 175233965Sjdp fb_label_max * sizeof (long)); 175377298Sobrien } /* if we needed to grow */ 175433965Sjdp 175533965Sjdp fb_labels[fb_label_count] = label; 175633965Sjdp fb_label_instances[fb_label_count] = 1; 175733965Sjdp ++fb_label_count; 175833965Sjdp} 175933965Sjdp 176077298Sobrienstatic long 1761130561Sobrienfb_label_instance (long label) 176233965Sjdp{ 176333965Sjdp long *i; 176433965Sjdp 176533965Sjdp if (label < FB_LABEL_SPECIAL) 176633965Sjdp { 176733965Sjdp return (fb_low_counter[label]); 176833965Sjdp } 176933965Sjdp 177033965Sjdp if (fb_labels != NULL) 177133965Sjdp { 177233965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 177333965Sjdp i < fb_labels + fb_label_count; ++i) 177433965Sjdp { 177533965Sjdp if (*i == label) 177633965Sjdp { 177733965Sjdp return (fb_label_instances[i - fb_labels]); 177877298Sobrien } /* if we find it */ 177977298Sobrien } /* for each existing label */ 178033965Sjdp } 178133965Sjdp 178233965Sjdp /* We didn't find the label, so this must be a reference to the 178333965Sjdp first instance. */ 178433965Sjdp return 0; 178533965Sjdp} 178633965Sjdp 178777298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 178833965Sjdp 178977298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 179077298Sobrien where n is the label number and m is the instance number. "L" makes 179177298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 179277298Sobrien ordinary symbol SHOULD get the same name as a local label 179377298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 179477298Sobrien 179577298Sobrien dollar labels get the same treatment, except that ^A is used in 179677298Sobrien place of ^B. */ 179777298Sobrien 179877298Sobrienchar * /* Return local label name. */ 1799130561Sobrienfb_label_name (long n, /* We just saw "n:", "nf" or "nb" : n a number. */ 1800130561Sobrien long augend /* 0 for nb, 1 for n:, nf. */) 180133965Sjdp{ 180233965Sjdp long i; 180377298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 180433965Sjdp static char symbol_name_build[24]; 180533965Sjdp register char *p; 180633965Sjdp register char *q; 180777298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 180833965Sjdp 180933965Sjdp know (n >= 0); 1810218822Sdim#ifdef TC_MMIX 1811218822Sdim know ((unsigned long) augend <= 2 /* See mmix_fb_label. */); 1812218822Sdim#else 1813218822Sdim know ((unsigned long) augend <= 1); 1814218822Sdim#endif 181533965Sjdp p = symbol_name_build; 181677298Sobrien#ifdef LOCAL_LABEL_PREFIX 181777298Sobrien *p++ = LOCAL_LABEL_PREFIX; 181877298Sobrien#endif 181933965Sjdp *p++ = 'L'; 182033965Sjdp 182177298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 182277298Sobrien /* Label number. */ 182333965Sjdp q = symbol_name_temporary; 182433965Sjdp for (*q++ = 0, i = n; i; ++q) 182533965Sjdp { 182633965Sjdp *q = i % 10 + '0'; 182733965Sjdp i /= 10; 182833965Sjdp } 182933965Sjdp while ((*p = *--q) != '\0') 183033965Sjdp ++p; 183133965Sjdp 183277298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 183333965Sjdp 183477298Sobrien /* Instance number. */ 183533965Sjdp q = symbol_name_temporary; 183633965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 183733965Sjdp { 183833965Sjdp *q = i % 10 + '0'; 183933965Sjdp i /= 10; 184033965Sjdp } 1841257360Ssbruno while ((*p++ = *--q) != '\0') 1842257360Ssbruno ;; 184333965Sjdp 184477298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 184533965Sjdp return (symbol_name_build); 184677298Sobrien} 184733965Sjdp 184877298Sobrien/* Decode name that may have been generated by foo_label_name() above. 184977298Sobrien If the name wasn't generated by foo_label_name(), then return it 185077298Sobrien unaltered. This is used for error messages. */ 185133965Sjdp 185233965Sjdpchar * 1853130561Sobriendecode_local_label_name (char *s) 185433965Sjdp{ 185533965Sjdp char *p; 185633965Sjdp char *symbol_decode; 185733965Sjdp int label_number; 185833965Sjdp int instance_number; 185933965Sjdp char *type; 186078828Sobrien const char *message_format; 186177298Sobrien int index = 0; 186233965Sjdp 186377298Sobrien#ifdef LOCAL_LABEL_PREFIX 186477298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 186577298Sobrien ++index; 186677298Sobrien#endif 186777298Sobrien 186877298Sobrien if (s[index] != 'L') 186933965Sjdp return s; 187033965Sjdp 187189857Sobrien for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p) 187233965Sjdp label_number = (10 * label_number) + *p - '0'; 187333965Sjdp 187477298Sobrien if (*p == DOLLAR_LABEL_CHAR) 187533965Sjdp type = "dollar"; 187677298Sobrien else if (*p == LOCAL_LABEL_CHAR) 187733965Sjdp type = "fb"; 187833965Sjdp else 187933965Sjdp return s; 188033965Sjdp 188189857Sobrien for (instance_number = 0, p++; ISDIGIT (*p); ++p) 188233965Sjdp instance_number = (10 * instance_number) + *p - '0'; 188333965Sjdp 188478828Sobrien message_format = _("\"%d\" (instance number %d of a %s label)"); 188533965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 188633965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 188733965Sjdp 188833965Sjdp return symbol_decode; 188933965Sjdp} 189033965Sjdp 189133965Sjdp/* Get the value of a symbol. */ 189233965Sjdp 189333965SjdpvalueT 1894130561SobrienS_GET_VALUE (symbolS *s) 189533965Sjdp{ 189660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 189789857Sobrien return resolve_symbol_value (s); 189860484Sobrien 189989857Sobrien if (!s->sy_resolved) 190089857Sobrien { 190189857Sobrien valueT val = resolve_symbol_value (s); 190289857Sobrien if (!finalize_syms) 190389857Sobrien return val; 190489857Sobrien } 1905218822Sdim if (S_IS_WEAKREFR (s)) 1906218822Sdim return S_GET_VALUE (s->sy_value.X_add_symbol); 1907218822Sdim 190833965Sjdp if (s->sy_value.X_op != O_constant) 190933965Sjdp { 191033965Sjdp if (! s->sy_resolved 191133965Sjdp || s->sy_value.X_op != O_symbol 191233965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 191389857Sobrien as_bad (_("attempt to get value of unresolved symbol `%s'"), 191433965Sjdp S_GET_NAME (s)); 191533965Sjdp } 191633965Sjdp return (valueT) s->sy_value.X_add_number; 191733965Sjdp} 191833965Sjdp 191933965Sjdp/* Set the value of a symbol. */ 192033965Sjdp 192133965Sjdpvoid 1922130561SobrienS_SET_VALUE (symbolS *s, valueT val) 192333965Sjdp{ 192460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 192560484Sobrien { 192689857Sobrien ((struct local_symbol *) s)->lsy_value = val; 192760484Sobrien return; 192860484Sobrien } 192960484Sobrien 193033965Sjdp s->sy_value.X_op = O_constant; 193133965Sjdp s->sy_value.X_add_number = (offsetT) val; 193233965Sjdp s->sy_value.X_unsigned = 0; 1933218822Sdim S_CLEAR_WEAKREFR (s); 193433965Sjdp} 193533965Sjdp 193633965Sjdpvoid 1937130561Sobriencopy_symbol_attributes (symbolS *dest, symbolS *src) 193833965Sjdp{ 193960484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 194060484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 194160484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 194260484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 194360484Sobrien 194433965Sjdp /* In an expression, transfer the settings of these flags. 194533965Sjdp The user can override later, of course. */ 194638889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 194733965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 194833965Sjdp 194933965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 195033965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 195133965Sjdp#endif 1952218822Sdim 1953218822Sdim#ifdef TC_COPY_SYMBOL_ATTRIBUTES 1954218822Sdim TC_COPY_SYMBOL_ATTRIBUTES (dest, src); 1955218822Sdim#endif 195633965Sjdp} 195733965Sjdp 195833965Sjdpint 1959130561SobrienS_IS_FUNCTION (symbolS *s) 196060484Sobrien{ 196160484Sobrien flagword flags; 196260484Sobrien 196360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 196460484Sobrien return 0; 196560484Sobrien 196660484Sobrien flags = s->bsym->flags; 196760484Sobrien 196860484Sobrien return (flags & BSF_FUNCTION) != 0; 196960484Sobrien} 197060484Sobrien 197160484Sobrienint 1972130561SobrienS_IS_EXTERNAL (symbolS *s) 197333965Sjdp{ 197460484Sobrien flagword flags; 197533965Sjdp 197660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197760484Sobrien return 0; 197860484Sobrien 197960484Sobrien flags = s->bsym->flags; 198060484Sobrien 198177298Sobrien /* Sanity check. */ 198238889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 198333965Sjdp abort (); 198433965Sjdp 198533965Sjdp return (flags & BSF_GLOBAL) != 0; 198633965Sjdp} 198733965Sjdp 198833965Sjdpint 1989130561SobrienS_IS_WEAK (symbolS *s) 199033965Sjdp{ 199160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 199260484Sobrien return 0; 1993218822Sdim /* Conceptually, a weakrefr is weak if the referenced symbol is. We 1994218822Sdim could probably handle a WEAKREFR as always weak though. E.g., if 1995218822Sdim the referenced symbol has lost its weak status, there's no reason 1996218822Sdim to keep handling the weakrefr as if it was weak. */ 1997218822Sdim if (S_IS_WEAKREFR (s)) 1998218822Sdim return S_IS_WEAK (s->sy_value.X_add_symbol); 199933965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 200033965Sjdp} 200133965Sjdp 200233965Sjdpint 2003218822SdimS_IS_WEAKREFR (symbolS *s) 2004218822Sdim{ 2005218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2006218822Sdim return 0; 2007218822Sdim return s->sy_weakrefr != 0; 2008218822Sdim} 2009218822Sdim 2010218822Sdimint 2011218822SdimS_IS_WEAKREFD (symbolS *s) 2012218822Sdim{ 2013218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2014218822Sdim return 0; 2015218822Sdim return s->sy_weakrefd != 0; 2016218822Sdim} 2017218822Sdim 2018218822Sdimint 2019130561SobrienS_IS_COMMON (symbolS *s) 202033965Sjdp{ 202160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202260484Sobrien return 0; 202333965Sjdp return bfd_is_com_section (s->bsym->section); 202433965Sjdp} 202533965Sjdp 202633965Sjdpint 2027130561SobrienS_IS_DEFINED (symbolS *s) 202833965Sjdp{ 202960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 203060484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 203133965Sjdp return s->bsym->section != undefined_section; 203233965Sjdp} 203333965Sjdp 2034130561Sobrien 2035130561Sobrien#ifndef EXTERN_FORCE_RELOC 2036130561Sobrien#define EXTERN_FORCE_RELOC IS_ELF 2037130561Sobrien#endif 2038130561Sobrien 2039130561Sobrien/* Return true for symbols that should not be reduced to section 2040130561Sobrien symbols or eliminated from expressions, because they may be 2041130561Sobrien overridden by the linker. */ 204233965Sjdpint 2043130561SobrienS_FORCE_RELOC (symbolS *s, int strict) 204433965Sjdp{ 204560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 2046130561Sobrien return ((struct local_symbol *) s)->lsy_section == undefined_section; 2047130561Sobrien 2048130561Sobrien return ((strict 2049130561Sobrien && ((s->bsym->flags & BSF_WEAK) != 0 2050130561Sobrien || (EXTERN_FORCE_RELOC 2051130561Sobrien && (s->bsym->flags & BSF_GLOBAL) != 0))) 2052130561Sobrien || s->bsym->section == undefined_section 2053130561Sobrien || bfd_is_com_section (s->bsym->section)); 2054130561Sobrien} 2055130561Sobrien 2056130561Sobrienint 2057130561SobrienS_IS_DEBUG (symbolS *s) 2058130561Sobrien{ 2059130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 206060484Sobrien return 0; 206133965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 206233965Sjdp return 1; 206333965Sjdp return 0; 206433965Sjdp} 206533965Sjdp 206633965Sjdpint 2067130561SobrienS_IS_LOCAL (symbolS *s) 206833965Sjdp{ 206960484Sobrien flagword flags; 207033965Sjdp const char *name; 207133965Sjdp 207260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207360484Sobrien return 1; 207460484Sobrien 207560484Sobrien flags = s->bsym->flags; 207660484Sobrien 207777298Sobrien /* Sanity check. */ 207838889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 207933965Sjdp abort (); 208033965Sjdp 208133965Sjdp if (bfd_get_section (s->bsym) == reg_section) 208233965Sjdp return 1; 208333965Sjdp 208438889Sjdp if (flag_strip_local_absolute 2085218822Sdim /* Keep BSF_FILE symbols in order to allow debuggers to identify 2086218822Sdim the source file even when the object file is stripped. */ 2087218822Sdim && (flags & (BSF_GLOBAL | BSF_FILE)) == 0 208838889Sjdp && bfd_get_section (s->bsym) == absolute_section) 208938889Sjdp return 1; 209038889Sjdp 209133965Sjdp name = S_GET_NAME (s); 209233965Sjdp return (name != NULL 209333965Sjdp && ! S_IS_DEBUG (s) 209477298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 209577298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 209633965Sjdp || (! flag_keep_locals 209733965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 209833965Sjdp || (flag_mri 209933965Sjdp && name[0] == '?' 210033965Sjdp && name[1] == '?'))))); 210133965Sjdp} 210233965Sjdp 210333965Sjdpint 2104218822SdimS_IS_STABD (symbolS *s) 210533965Sjdp{ 2106218822Sdim return S_GET_NAME (s) == 0; 210733965Sjdp} 210833965Sjdp 210933965Sjdpint 2110218822SdimS_IS_VOLATILE (const symbolS *s) 211133965Sjdp{ 2112218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2113218822Sdim return 0; 2114218822Sdim return s->sy_volatile; 211533965Sjdp} 211633965Sjdp 2117218822Sdimint 2118218822SdimS_IS_FORWARD_REF (const symbolS *s) 2119218822Sdim{ 2120218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2121218822Sdim return 0; 2122218822Sdim return s->sy_forward_ref; 2123218822Sdim} 2124218822Sdim 2125104834Sobrienconst char * 2126130561SobrienS_GET_NAME (symbolS *s) 212733965Sjdp{ 212860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212960484Sobrien return ((struct local_symbol *) s)->lsy_name; 213033965Sjdp return s->bsym->name; 213133965Sjdp} 213233965Sjdp 213333965SjdpsegT 2134130561SobrienS_GET_SEGMENT (symbolS *s) 213533965Sjdp{ 213660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213760484Sobrien return ((struct local_symbol *) s)->lsy_section; 213833965Sjdp return s->bsym->section; 213933965Sjdp} 214033965Sjdp 214133965Sjdpvoid 2142130561SobrienS_SET_SEGMENT (symbolS *s, segT seg) 214333965Sjdp{ 214438889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 214538889Sjdp faults assigning back to const global symbols such as *ABS*, but it 214638889Sjdp shouldn't happen anyway. */ 214738889Sjdp 214860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 214960484Sobrien { 215060484Sobrien if (seg == reg_section) 215160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 215260484Sobrien else 215360484Sobrien { 215460484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 215560484Sobrien return; 215660484Sobrien } 215760484Sobrien } 215860484Sobrien 215938889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 216038889Sjdp { 216138889Sjdp if (s->bsym->section != seg) 216277298Sobrien abort (); 216338889Sjdp } 216438889Sjdp else 216538889Sjdp s->bsym->section = seg; 216633965Sjdp} 216733965Sjdp 216833965Sjdpvoid 2169130561SobrienS_SET_EXTERNAL (symbolS *s) 217033965Sjdp{ 217160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 217333965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 217433965Sjdp { 217533965Sjdp /* Let .weak override .global. */ 217633965Sjdp return; 217733965Sjdp } 217878828Sobrien if (s->bsym->flags & BSF_SECTION_SYM) 217978828Sobrien { 218078828Sobrien char * file; 218178828Sobrien unsigned int line; 2182104834Sobrien 218378828Sobrien /* Do not reassign section symbols. */ 218478828Sobrien as_where (& file, & line); 218578828Sobrien as_warn_where (file, line, 218689857Sobrien _("section symbols are already global")); 218778828Sobrien return; 218878828Sobrien } 218933965Sjdp s->bsym->flags |= BSF_GLOBAL; 219077298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 2191218822Sdim 2192218822Sdim#ifdef USE_UNIQUE 2193218822Sdim if (! an_external_name && S_GET_NAME(s)[0] != '.') 2194218822Sdim an_external_name = S_GET_NAME (s); 2195218822Sdim#endif 219633965Sjdp} 219733965Sjdp 219833965Sjdpvoid 2199130561SobrienS_CLEAR_EXTERNAL (symbolS *s) 220033965Sjdp{ 220160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 220260484Sobrien return; 220333965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 220433965Sjdp { 220533965Sjdp /* Let .weak override. */ 220633965Sjdp return; 220733965Sjdp } 220833965Sjdp s->bsym->flags |= BSF_LOCAL; 220977298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 221033965Sjdp} 221133965Sjdp 221233965Sjdpvoid 2213130561SobrienS_SET_WEAK (symbolS *s) 221433965Sjdp{ 221560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 221660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2217218822Sdim#ifdef obj_set_weak_hook 2218218822Sdim obj_set_weak_hook (s); 2219218822Sdim#endif 222033965Sjdp s->bsym->flags |= BSF_WEAK; 222177298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 222233965Sjdp} 222333965Sjdp 222433965Sjdpvoid 2225218822SdimS_SET_WEAKREFR (symbolS *s) 2226218822Sdim{ 2227218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2228218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2229218822Sdim s->sy_weakrefr = 1; 2230218822Sdim /* If the alias was already used, make sure we mark the target as 2231218822Sdim used as well, otherwise it might be dropped from the symbol 2232218822Sdim table. This may have unintended side effects if the alias is 2233218822Sdim later redirected to another symbol, such as keeping the unused 2234218822Sdim previous target in the symbol table. Since it will be weak, it's 2235218822Sdim not a big deal. */ 2236218822Sdim if (s->sy_used) 2237218822Sdim symbol_mark_used (s->sy_value.X_add_symbol); 2238218822Sdim} 2239218822Sdim 2240218822Sdimvoid 2241218822SdimS_CLEAR_WEAKREFR (symbolS *s) 2242218822Sdim{ 2243218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2244218822Sdim return; 2245218822Sdim s->sy_weakrefr = 0; 2246218822Sdim} 2247218822Sdim 2248218822Sdimvoid 2249218822SdimS_SET_WEAKREFD (symbolS *s) 2250218822Sdim{ 2251218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2252218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2253218822Sdim s->sy_weakrefd = 1; 2254218822Sdim S_SET_WEAK (s); 2255218822Sdim} 2256218822Sdim 2257218822Sdimvoid 2258218822SdimS_CLEAR_WEAKREFD (symbolS *s) 2259218822Sdim{ 2260218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2261218822Sdim return; 2262218822Sdim if (s->sy_weakrefd) 2263218822Sdim { 2264218822Sdim s->sy_weakrefd = 0; 2265218822Sdim /* If a weakref target symbol is weak, then it was never 2266218822Sdim referenced directly before, not even in a .global directive, 2267218822Sdim so decay it to local. If it remains undefined, it will be 2268218822Sdim later turned into a global, like any other undefined 2269218822Sdim symbol. */ 2270218822Sdim if (s->bsym->flags & BSF_WEAK) 2271218822Sdim { 2272218822Sdim#ifdef obj_clear_weak_hook 2273218822Sdim obj_clear_weak_hook (s); 2274218822Sdim#endif 2275218822Sdim s->bsym->flags &= ~BSF_WEAK; 2276218822Sdim s->bsym->flags |= BSF_LOCAL; 2277218822Sdim } 2278218822Sdim } 2279218822Sdim} 2280218822Sdim 2281218822Sdimvoid 2282130561SobrienS_SET_THREAD_LOCAL (symbolS *s) 228333965Sjdp{ 228460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 2285130561Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2286130561Sobrien if (bfd_is_com_section (s->bsym->section) 2287130561Sobrien && (s->bsym->flags & BSF_THREAD_LOCAL) != 0) 2288130561Sobrien return; 2289130561Sobrien s->bsym->flags |= BSF_THREAD_LOCAL; 2290130561Sobrien if ((s->bsym->flags & BSF_FUNCTION) != 0) 2291130561Sobrien as_bad (_("Accessing function `%s' as thread-local object"), 2292130561Sobrien S_GET_NAME (s)); 2293130561Sobrien else if (! bfd_is_und_section (s->bsym->section) 2294130561Sobrien && (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0) 2295130561Sobrien as_bad (_("Accessing `%s' as thread-local object"), 2296130561Sobrien S_GET_NAME (s)); 2297130561Sobrien} 2298130561Sobrien 2299130561Sobrienvoid 2300218822SdimS_SET_NAME (symbolS *s, const char *name) 2301130561Sobrien{ 2302130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 230360484Sobrien { 230460484Sobrien ((struct local_symbol *) s)->lsy_name = name; 230560484Sobrien return; 230660484Sobrien } 230733965Sjdp s->bsym->name = name; 230833965Sjdp} 230933965Sjdp 2310218822Sdimvoid 2311218822SdimS_SET_VOLATILE (symbolS *s) 2312218822Sdim{ 2313218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2314218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2315218822Sdim s->sy_volatile = 1; 2316218822Sdim} 231760484Sobrien 2318218822Sdimvoid 2319218822SdimS_CLEAR_VOLATILE (symbolS *s) 2320218822Sdim{ 2321218822Sdim if (!LOCAL_SYMBOL_CHECK (s)) 2322218822Sdim s->sy_volatile = 0; 2323218822Sdim} 2324218822Sdim 2325218822Sdimvoid 2326218822SdimS_SET_FORWARD_REF (symbolS *s) 2327218822Sdim{ 2328218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2329218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2330218822Sdim s->sy_forward_ref = 1; 2331218822Sdim} 2332218822Sdim 233360484Sobrien/* Return the previous symbol in a chain. */ 233460484Sobrien 233560484SobriensymbolS * 2336130561Sobriensymbol_previous (symbolS *s) 233760484Sobrien{ 233860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 233960484Sobrien abort (); 234060484Sobrien return s->sy_previous; 234160484Sobrien} 234260484Sobrien 234360484Sobrien/* Return the next symbol in a chain. */ 234460484Sobrien 234560484SobriensymbolS * 2346130561Sobriensymbol_next (symbolS *s) 234760484Sobrien{ 234860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 234960484Sobrien abort (); 235060484Sobrien return s->sy_next; 235160484Sobrien} 235260484Sobrien 235360484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 235460484Sobrien 235560484SobrienexpressionS * 2356130561Sobriensymbol_get_value_expression (symbolS *s) 235760484Sobrien{ 235860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 235960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 236060484Sobrien return &s->sy_value; 236160484Sobrien} 236260484Sobrien 236360484Sobrien/* Set the value of a symbol to an expression. */ 236460484Sobrien 236533965Sjdpvoid 2366130561Sobriensymbol_set_value_expression (symbolS *s, const expressionS *exp) 236760484Sobrien{ 236860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 236960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 237060484Sobrien s->sy_value = *exp; 2371218822Sdim S_CLEAR_WEAKREFR (s); 237260484Sobrien} 237360484Sobrien 2374218822Sdim/* Return a pointer to the X_add_number component of a symbol. */ 2375218822Sdim 2376218822SdimoffsetT * 2377218822Sdimsymbol_X_add_number (symbolS *s) 2378218822Sdim{ 2379218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2380218822Sdim return (offsetT *) &((struct local_symbol *) s)->lsy_value; 2381218822Sdim 2382218822Sdim return &s->sy_value.X_add_number; 2383218822Sdim} 2384218822Sdim 2385130561Sobrien/* Set the value of SYM to the current position in the current segment. */ 2386130561Sobrien 2387130561Sobrienvoid 2388130561Sobriensymbol_set_value_now (symbolS *sym) 2389130561Sobrien{ 2390130561Sobrien S_SET_SEGMENT (sym, now_seg); 2391130561Sobrien S_SET_VALUE (sym, frag_now_fix ()); 2392130561Sobrien symbol_set_frag (sym, frag_now); 2393130561Sobrien} 2394130561Sobrien 239560484Sobrien/* Set the frag of a symbol. */ 239660484Sobrien 239760484Sobrienvoid 2398130561Sobriensymbol_set_frag (symbolS *s, fragS *f) 239960484Sobrien{ 240060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 240160484Sobrien { 240260484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 240360484Sobrien return; 240460484Sobrien } 240560484Sobrien s->sy_frag = f; 2406218822Sdim S_CLEAR_WEAKREFR (s); 240760484Sobrien} 240860484Sobrien 240960484Sobrien/* Return the frag of a symbol. */ 241060484Sobrien 241160484SobrienfragS * 2412130561Sobriensymbol_get_frag (symbolS *s) 241360484Sobrien{ 241460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 241560484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 241660484Sobrien return s->sy_frag; 241760484Sobrien} 241860484Sobrien 241960484Sobrien/* Mark a symbol as having been used. */ 242060484Sobrien 242160484Sobrienvoid 2422130561Sobriensymbol_mark_used (symbolS *s) 242360484Sobrien{ 242460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 242560484Sobrien return; 242660484Sobrien s->sy_used = 1; 2427218822Sdim if (S_IS_WEAKREFR (s)) 2428218822Sdim symbol_mark_used (s->sy_value.X_add_symbol); 242960484Sobrien} 243060484Sobrien 243160484Sobrien/* Clear the mark of whether a symbol has been used. */ 243260484Sobrien 243360484Sobrienvoid 2434130561Sobriensymbol_clear_used (symbolS *s) 243560484Sobrien{ 243660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 243760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 243860484Sobrien s->sy_used = 0; 243960484Sobrien} 244060484Sobrien 244160484Sobrien/* Return whether a symbol has been used. */ 244260484Sobrien 244360484Sobrienint 2444130561Sobriensymbol_used_p (symbolS *s) 244560484Sobrien{ 244660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 244760484Sobrien return 1; 244860484Sobrien return s->sy_used; 244960484Sobrien} 245060484Sobrien 245160484Sobrien/* Mark a symbol as having been used in a reloc. */ 245260484Sobrien 245360484Sobrienvoid 2454130561Sobriensymbol_mark_used_in_reloc (symbolS *s) 245560484Sobrien{ 245660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 245760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 245860484Sobrien s->sy_used_in_reloc = 1; 245960484Sobrien} 246060484Sobrien 246160484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 246260484Sobrien 246360484Sobrienvoid 2464130561Sobriensymbol_clear_used_in_reloc (symbolS *s) 246560484Sobrien{ 246660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 246760484Sobrien return; 246860484Sobrien s->sy_used_in_reloc = 0; 246960484Sobrien} 247060484Sobrien 247160484Sobrien/* Return whether a symbol has been used in a reloc. */ 247260484Sobrien 247360484Sobrienint 2474130561Sobriensymbol_used_in_reloc_p (symbolS *s) 247560484Sobrien{ 247660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 247760484Sobrien return 0; 247860484Sobrien return s->sy_used_in_reloc; 247960484Sobrien} 248060484Sobrien 248160484Sobrien/* Mark a symbol as an MRI common symbol. */ 248260484Sobrien 248360484Sobrienvoid 2484130561Sobriensymbol_mark_mri_common (symbolS *s) 248560484Sobrien{ 248660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 248760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 248860484Sobrien s->sy_mri_common = 1; 248960484Sobrien} 249060484Sobrien 249160484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 249260484Sobrien 249360484Sobrienvoid 2494130561Sobriensymbol_clear_mri_common (symbolS *s) 249560484Sobrien{ 249660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 249760484Sobrien return; 249860484Sobrien s->sy_mri_common = 0; 249960484Sobrien} 250060484Sobrien 250160484Sobrien/* Return whether a symbol is an MRI common symbol. */ 250260484Sobrien 250360484Sobrienint 2504130561Sobriensymbol_mri_common_p (symbolS *s) 250560484Sobrien{ 250660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 250760484Sobrien return 0; 250860484Sobrien return s->sy_mri_common; 250960484Sobrien} 251060484Sobrien 251160484Sobrien/* Mark a symbol as having been written. */ 251260484Sobrien 251360484Sobrienvoid 2514130561Sobriensymbol_mark_written (symbolS *s) 251560484Sobrien{ 251660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 251760484Sobrien return; 251860484Sobrien s->written = 1; 251960484Sobrien} 252060484Sobrien 252160484Sobrien/* Clear the mark of whether a symbol has been written. */ 252260484Sobrien 252360484Sobrienvoid 2524130561Sobriensymbol_clear_written (symbolS *s) 252560484Sobrien{ 252660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 252760484Sobrien return; 252860484Sobrien s->written = 0; 252960484Sobrien} 253060484Sobrien 253160484Sobrien/* Return whether a symbol has been written. */ 253260484Sobrien 253360484Sobrienint 2534130561Sobriensymbol_written_p (symbolS *s) 253560484Sobrien{ 253660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 253760484Sobrien return 0; 253860484Sobrien return s->written; 253960484Sobrien} 254060484Sobrien 254160484Sobrien/* Mark a symbol has having been resolved. */ 254260484Sobrien 254360484Sobrienvoid 2544130561Sobriensymbol_mark_resolved (symbolS *s) 254560484Sobrien{ 254660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 254760484Sobrien { 254860484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 254960484Sobrien return; 255060484Sobrien } 255160484Sobrien s->sy_resolved = 1; 255260484Sobrien} 255360484Sobrien 255460484Sobrien/* Return whether a symbol has been resolved. */ 255560484Sobrien 255660484Sobrienint 2557130561Sobriensymbol_resolved_p (symbolS *s) 255860484Sobrien{ 255960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 256060484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 256160484Sobrien return s->sy_resolved; 256260484Sobrien} 256360484Sobrien 256460484Sobrien/* Return whether a symbol is a section symbol. */ 256560484Sobrien 256660484Sobrienint 2567130561Sobriensymbol_section_p (symbolS *s ATTRIBUTE_UNUSED) 256860484Sobrien{ 256960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 257060484Sobrien return 0; 257160484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 257260484Sobrien} 257360484Sobrien 257460484Sobrien/* Return whether a symbol is equated to another symbol. */ 257560484Sobrien 257660484Sobrienint 2577130561Sobriensymbol_equated_p (symbolS *s) 257860484Sobrien{ 257960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 258060484Sobrien return 0; 258160484Sobrien return s->sy_value.X_op == O_symbol; 258260484Sobrien} 258360484Sobrien 258489857Sobrien/* Return whether a symbol is equated to another symbol, and should be 258589857Sobrien treated specially when writing out relocs. */ 258689857Sobrien 258789857Sobrienint 2588130561Sobriensymbol_equated_reloc_p (symbolS *s) 258989857Sobrien{ 259089857Sobrien if (LOCAL_SYMBOL_CHECK (s)) 259189857Sobrien return 0; 259289857Sobrien /* X_op_symbol, normally not used for O_symbol, is set by 259389857Sobrien resolve_symbol_value to flag expression syms that have been 259489857Sobrien equated. */ 259589857Sobrien return (s->sy_value.X_op == O_symbol 2596218822Sdim#if defined (OBJ_COFF) && defined (TE_PE) 2597218822Sdim && ! S_IS_WEAK (s) 2598218822Sdim#endif 259989857Sobrien && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL) 260089857Sobrien || ! S_IS_DEFINED (s) 260189857Sobrien || S_IS_COMMON (s))); 260289857Sobrien} 260389857Sobrien 260460484Sobrien/* Return whether a symbol has a constant value. */ 260560484Sobrien 260660484Sobrienint 2607130561Sobriensymbol_constant_p (symbolS *s) 260860484Sobrien{ 260960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 261060484Sobrien return 1; 261160484Sobrien return s->sy_value.X_op == O_constant; 261260484Sobrien} 261360484Sobrien 2614218822Sdim/* Return whether a symbol was cloned and thus removed from the global 2615218822Sdim symbol list. */ 261660484Sobrien 2617218822Sdimint 2618218822Sdimsymbol_shadow_p (symbolS *s) 2619218822Sdim{ 2620218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2621218822Sdim return 0; 2622218822Sdim return s->sy_next == s; 2623218822Sdim} 2624218822Sdim 262560484Sobrien/* Return the BFD symbol for a symbol. */ 262660484Sobrien 262760484Sobrienasymbol * 2628130561Sobriensymbol_get_bfdsym (symbolS *s) 262960484Sobrien{ 263060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 263160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 263260484Sobrien return s->bsym; 263360484Sobrien} 263460484Sobrien 263560484Sobrien/* Set the BFD symbol for a symbol. */ 263660484Sobrien 263760484Sobrienvoid 2638130561Sobriensymbol_set_bfdsym (symbolS *s, asymbol *bsym) 263960484Sobrien{ 264060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 264160484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2642218822Sdim /* Usually, it is harmless to reset a symbol to a BFD section 2643218822Sdim symbol. For example, obj_elf_change_section sets the BFD symbol 2644218822Sdim of an old symbol with the newly created section symbol. But when 2645218822Sdim we have multiple sections with the same name, the newly created 2646218822Sdim section may have the same name as an old section. We check if the 2647218822Sdim old symbol has been already marked as a section symbol before 2648218822Sdim resetting it. */ 2649218822Sdim if ((s->bsym->flags & BSF_SECTION_SYM) == 0) 2650218822Sdim s->bsym = bsym; 2651218822Sdim /* else XXX - What do we do now ? */ 265260484Sobrien} 265360484Sobrien 265460484Sobrien#ifdef OBJ_SYMFIELD_TYPE 265560484Sobrien 265660484Sobrien/* Get a pointer to the object format information for a symbol. */ 265760484Sobrien 265860484SobrienOBJ_SYMFIELD_TYPE * 2659130561Sobriensymbol_get_obj (symbolS *s) 266060484Sobrien{ 266160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 266260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 266360484Sobrien return &s->sy_obj; 266460484Sobrien} 266560484Sobrien 266660484Sobrien/* Set the object format information for a symbol. */ 266760484Sobrien 266860484Sobrienvoid 2669130561Sobriensymbol_set_obj (symbolS *s, OBJ_SYMFIELD_TYPE *o) 267060484Sobrien{ 267160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 267260484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 267360484Sobrien s->sy_obj = *o; 267460484Sobrien} 267560484Sobrien 267660484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 267760484Sobrien 267860484Sobrien#ifdef TC_SYMFIELD_TYPE 267960484Sobrien 268060484Sobrien/* Get a pointer to the processor information for a symbol. */ 268160484Sobrien 268260484SobrienTC_SYMFIELD_TYPE * 2683130561Sobriensymbol_get_tc (symbolS *s) 268460484Sobrien{ 268560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 268660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 268760484Sobrien return &s->sy_tc; 268860484Sobrien} 268960484Sobrien 269060484Sobrien/* Set the processor information for a symbol. */ 269160484Sobrien 269260484Sobrienvoid 2693130561Sobriensymbol_set_tc (symbolS *s, TC_SYMFIELD_TYPE *o) 269460484Sobrien{ 269560484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 269660484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 269760484Sobrien s->sy_tc = *o; 269860484Sobrien} 269960484Sobrien 270060484Sobrien#endif /* TC_SYMFIELD_TYPE */ 270160484Sobrien 270260484Sobrienvoid 2703130561Sobriensymbol_begin (void) 270433965Sjdp{ 270533965Sjdp symbol_lastP = NULL; 270677298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 270733965Sjdp sy_hash = hash_new (); 270860484Sobrien local_hash = hash_new (); 270933965Sjdp 271033965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 271133965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 271233965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 271333965Sjdp#endif 271433965Sjdp abs_symbol.sy_value.X_op = O_constant; 271533965Sjdp abs_symbol.sy_frag = &zero_address_frag; 271633965Sjdp 271733965Sjdp if (LOCAL_LABELS_FB) 271833965Sjdp fb_label_init (); 271933965Sjdp} 272033965Sjdp 272133965Sjdpint indent_level; 272233965Sjdp 272360484Sobrien/* Maximum indent level. 272460484Sobrien Available for modification inside a gdb session. */ 2725218822Sdimstatic int max_indent_level = 8; 272660484Sobrien 272733965Sjdpvoid 2728130561Sobrienprint_symbol_value_1 (FILE *file, symbolS *sym) 272933965Sjdp{ 273033965Sjdp const char *name = S_GET_NAME (sym); 273133965Sjdp if (!name || !name[0]) 273233965Sjdp name = "(unnamed)"; 273333965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 273460484Sobrien 273560484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 273660484Sobrien { 273760484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 273860484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 273960484Sobrien && local_symbol_get_frag (locsym) != NULL) 274060484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 274160484Sobrien if (local_symbol_resolved_p (locsym)) 274260484Sobrien fprintf (file, " resolved"); 274360484Sobrien fprintf (file, " local"); 274460484Sobrien } 274560484Sobrien else 274660484Sobrien { 274760484Sobrien if (sym->sy_frag != &zero_address_frag) 274860484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 274960484Sobrien if (sym->written) 275060484Sobrien fprintf (file, " written"); 275160484Sobrien if (sym->sy_resolved) 275260484Sobrien fprintf (file, " resolved"); 275360484Sobrien else if (sym->sy_resolving) 275460484Sobrien fprintf (file, " resolving"); 275560484Sobrien if (sym->sy_used_in_reloc) 275660484Sobrien fprintf (file, " used-in-reloc"); 275760484Sobrien if (sym->sy_used) 275860484Sobrien fprintf (file, " used"); 275960484Sobrien if (S_IS_LOCAL (sym)) 276060484Sobrien fprintf (file, " local"); 2761218822Sdim if (S_IS_EXTERNAL (sym)) 276260484Sobrien fprintf (file, " extern"); 2763218822Sdim if (S_IS_WEAK (sym)) 2764218822Sdim fprintf (file, " weak"); 276560484Sobrien if (S_IS_DEBUG (sym)) 276660484Sobrien fprintf (file, " debug"); 276760484Sobrien if (S_IS_DEFINED (sym)) 276860484Sobrien fprintf (file, " defined"); 276960484Sobrien } 2770218822Sdim if (S_IS_WEAKREFR (sym)) 2771218822Sdim fprintf (file, " weakrefr"); 2772218822Sdim if (S_IS_WEAKREFD (sym)) 2773218822Sdim fprintf (file, " weakrefd"); 277433965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 277560484Sobrien if (symbol_resolved_p (sym)) 277633965Sjdp { 277733965Sjdp segT s = S_GET_SEGMENT (sym); 277833965Sjdp 277933965Sjdp if (s != undefined_section 2780104834Sobrien && s != expr_section) 278133965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 278233965Sjdp } 278360484Sobrien else if (indent_level < max_indent_level 278460484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 278533965Sjdp { 278633965Sjdp indent_level++; 278733965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 278860484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 278960484Sobrien fprintf (file, "constant %lx", 279089857Sobrien (long) ((struct local_symbol *) sym)->lsy_value); 279160484Sobrien else 279260484Sobrien print_expr_1 (file, &sym->sy_value); 279333965Sjdp fprintf (file, ">"); 279433965Sjdp indent_level--; 279533965Sjdp } 279633965Sjdp fflush (file); 279733965Sjdp} 279833965Sjdp 279933965Sjdpvoid 2800130561Sobrienprint_symbol_value (symbolS *sym) 280133965Sjdp{ 280233965Sjdp indent_level = 0; 280333965Sjdp print_symbol_value_1 (stderr, sym); 280433965Sjdp fprintf (stderr, "\n"); 280533965Sjdp} 280633965Sjdp 280760484Sobrienstatic void 2808130561Sobrienprint_binary (FILE *file, const char *name, expressionS *exp) 280960484Sobrien{ 281060484Sobrien indent_level++; 281160484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 281260484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 281360484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 281460484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 281560484Sobrien fprintf (file, ">"); 281660484Sobrien indent_level--; 281760484Sobrien} 281860484Sobrien 281933965Sjdpvoid 2820130561Sobrienprint_expr_1 (FILE *file, expressionS *exp) 282133965Sjdp{ 282233965Sjdp fprintf (file, "expr %lx ", (long) exp); 282333965Sjdp switch (exp->X_op) 282433965Sjdp { 282533965Sjdp case O_illegal: 282633965Sjdp fprintf (file, "illegal"); 282733965Sjdp break; 282833965Sjdp case O_absent: 282933965Sjdp fprintf (file, "absent"); 283033965Sjdp break; 283133965Sjdp case O_constant: 283233965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 283333965Sjdp break; 283433965Sjdp case O_symbol: 283533965Sjdp indent_level++; 283633965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 283733965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 283833965Sjdp fprintf (file, ">"); 283933965Sjdp maybe_print_addnum: 284033965Sjdp if (exp->X_add_number) 284133965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 284233965Sjdp (long) exp->X_add_number); 284333965Sjdp indent_level--; 284433965Sjdp break; 284533965Sjdp case O_register: 284633965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 284733965Sjdp break; 284833965Sjdp case O_big: 284933965Sjdp fprintf (file, "big"); 285033965Sjdp break; 285133965Sjdp case O_uminus: 285233965Sjdp fprintf (file, "uminus -<"); 285333965Sjdp indent_level++; 285433965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 285533965Sjdp fprintf (file, ">"); 285633965Sjdp goto maybe_print_addnum; 285733965Sjdp case O_bit_not: 285833965Sjdp fprintf (file, "bit_not"); 285933965Sjdp break; 286033965Sjdp case O_multiply: 286160484Sobrien print_binary (file, "multiply", exp); 286233965Sjdp break; 286333965Sjdp case O_divide: 286460484Sobrien print_binary (file, "divide", exp); 286533965Sjdp break; 286633965Sjdp case O_modulus: 286760484Sobrien print_binary (file, "modulus", exp); 286833965Sjdp break; 286933965Sjdp case O_left_shift: 287060484Sobrien print_binary (file, "lshift", exp); 287133965Sjdp break; 287233965Sjdp case O_right_shift: 287360484Sobrien print_binary (file, "rshift", exp); 287433965Sjdp break; 287533965Sjdp case O_bit_inclusive_or: 287660484Sobrien print_binary (file, "bit_ior", exp); 287733965Sjdp break; 287833965Sjdp case O_bit_exclusive_or: 287960484Sobrien print_binary (file, "bit_xor", exp); 288033965Sjdp break; 288133965Sjdp case O_bit_and: 288260484Sobrien print_binary (file, "bit_and", exp); 288333965Sjdp break; 288433965Sjdp case O_eq: 288560484Sobrien print_binary (file, "eq", exp); 288633965Sjdp break; 288733965Sjdp case O_ne: 288860484Sobrien print_binary (file, "ne", exp); 288933965Sjdp break; 289033965Sjdp case O_lt: 289160484Sobrien print_binary (file, "lt", exp); 289233965Sjdp break; 289333965Sjdp case O_le: 289460484Sobrien print_binary (file, "le", exp); 289533965Sjdp break; 289633965Sjdp case O_ge: 289760484Sobrien print_binary (file, "ge", exp); 289833965Sjdp break; 289933965Sjdp case O_gt: 290060484Sobrien print_binary (file, "gt", exp); 290133965Sjdp break; 290233965Sjdp case O_logical_and: 290360484Sobrien print_binary (file, "logical_and", exp); 290433965Sjdp break; 290533965Sjdp case O_logical_or: 290660484Sobrien print_binary (file, "logical_or", exp); 290733965Sjdp break; 290833965Sjdp case O_add: 290933965Sjdp indent_level++; 291033965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 291133965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 291233965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 291333965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 291433965Sjdp fprintf (file, ">"); 291533965Sjdp goto maybe_print_addnum; 291633965Sjdp case O_subtract: 291733965Sjdp indent_level++; 291833965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 291933965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 292033965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 292133965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 292233965Sjdp fprintf (file, ">"); 292333965Sjdp goto maybe_print_addnum; 292433965Sjdp default: 292533965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 292633965Sjdp break; 292733965Sjdp } 292833965Sjdp fflush (stdout); 292933965Sjdp} 293033965Sjdp 293133965Sjdpvoid 2932130561Sobrienprint_expr (expressionS *exp) 293333965Sjdp{ 293433965Sjdp print_expr_1 (stderr, exp); 293533965Sjdp fprintf (stderr, "\n"); 293633965Sjdp} 293733965Sjdp 293833965Sjdpvoid 2939130561Sobriensymbol_print_statistics (FILE *file) 294033965Sjdp{ 294133965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 294260484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 294360484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 294460484Sobrien local_symbol_count, local_symbol_conversion_count); 2945218822Sdim} 2946218822Sdim 2947218822Sdim#ifdef OBJ_COMPLEX_RELC 2948218822Sdim 2949218822Sdim/* Convert given symbol to a new complex-relocation symbol name. This 2950218822Sdim may be a recursive function, since it might be called for non-leaf 2951218822Sdim nodes (plain symbols) in the expression tree. The caller owns the 2952218822Sdim returning string, so should free it eventually. Errors are 2953218822Sdim indicated via as_bad and a NULL return value. The given symbol 2954218822Sdim is marked with sy_used_in_reloc. */ 2955218822Sdim 2956218822Sdimchar * 2957218822Sdimsymbol_relc_make_sym (symbolS * sym) 2958218822Sdim{ 2959218822Sdim char * terminal = NULL; 2960218822Sdim const char * sname; 2961218822Sdim char typetag; 2962218822Sdim int sname_len; 2963218822Sdim 2964218822Sdim assert (sym != NULL); 2965218822Sdim 2966218822Sdim /* Recurse to symbol_relc_make_expr if this symbol 2967218822Sdim is defined as an expression or a plain value. */ 2968218822Sdim if ( S_GET_SEGMENT (sym) == expr_section 2969218822Sdim || S_GET_SEGMENT (sym) == absolute_section) 2970218822Sdim return symbol_relc_make_expr (& sym->sy_value); 2971218822Sdim 2972218822Sdim /* This may be a "fake symbol" L0\001, referring to ".". 2973218822Sdim Write out a special null symbol to refer to this position. */ 2974218822Sdim if (! strcmp (S_GET_NAME (sym), FAKE_LABEL_NAME)) 2975218822Sdim return xstrdup ("."); 2976218822Sdim 2977218822Sdim /* We hope this is a plain leaf symbol. Construct the encoding 2978218822Sdim as {S,s}II...:CCCCCCC.... 2979218822Sdim where 'S'/'s' means section symbol / plain symbol 2980218822Sdim III is decimal for the symbol name length 2981218822Sdim CCC is the symbol name itself. */ 2982218822Sdim symbol_mark_used_in_reloc (sym); 2983218822Sdim 2984218822Sdim sname = S_GET_NAME (sym); 2985218822Sdim sname_len = strlen (sname); 2986218822Sdim typetag = symbol_section_p (sym) ? 'S' : 's'; 2987218822Sdim 2988218822Sdim terminal = xmalloc (1 /* S or s */ 2989218822Sdim + 8 /* sname_len in decimal */ 2990218822Sdim + 1 /* _ spacer */ 2991218822Sdim + sname_len /* name itself */ 2992218822Sdim + 1 /* \0 */ ); 2993218822Sdim 2994218822Sdim sprintf (terminal, "%c%d:%s", typetag, sname_len, sname); 2995218822Sdim return terminal; 2996218822Sdim} 2997218822Sdim 2998218822Sdim/* Convert given value to a new complex-relocation symbol name. This 2999218822Sdim is a non-recursive function, since it is be called for leaf nodes 3000218822Sdim (plain values) in the expression tree. The caller owns the 3001218822Sdim returning string, so should free() it eventually. No errors. */ 3002218822Sdim 3003218822Sdimchar * 3004218822Sdimsymbol_relc_make_value (offsetT val) 3005218822Sdim{ 3006218822Sdim char * terminal = xmalloc (28); /* Enough for long long. */ 3007218822Sdim 3008218822Sdim terminal[0] = '#'; 3009218822Sdim sprintf_vma (& terminal[1], val); 3010218822Sdim return terminal; 3011218822Sdim} 3012218822Sdim 3013218822Sdim/* Convert given expression to a new complex-relocation symbol name. 3014218822Sdim This is a recursive function, since it traverses the entire given 3015218822Sdim expression tree. The caller owns the returning string, so should 3016218822Sdim free() it eventually. Errors are indicated via as_bad() and a NULL 3017218822Sdim return value. */ 3018218822Sdim 3019218822Sdimchar * 3020218822Sdimsymbol_relc_make_expr (expressionS * exp) 3021218822Sdim{ 3022218822Sdim char * opstr = NULL; /* Operator prefix string. */ 3023218822Sdim int arity = 0; /* Arity of this operator. */ 3024218822Sdim char * operands[3]; /* Up to three operands. */ 3025218822Sdim char * concat_string = NULL; 3026218822Sdim 3027218822Sdim operands[0] = operands[1] = operands[2] = NULL; 3028218822Sdim 3029218822Sdim assert (exp != NULL); 3030218822Sdim 3031218822Sdim /* Match known operators -> fill in opstr, arity, operands[] and fall 3032218822Sdim through to construct subexpression fragments; may instead return 3033218822Sdim string directly for leaf nodes. */ 3034218822Sdim 3035218822Sdim /* See expr.h for the meaning of all these enums. Many operators 3036218822Sdim have an unnatural arity (X_add_number implicitly added). The 3037218822Sdim conversion logic expands them to explicit "+" subexpressions. */ 3038218822Sdim 3039218822Sdim switch (exp->X_op) 3040218822Sdim { 3041218822Sdim default: 3042218822Sdim as_bad ("Unknown expression operator (enum %d)", exp->X_op); 3043218822Sdim break; 3044218822Sdim 3045218822Sdim /* Leaf nodes. */ 3046218822Sdim case O_constant: 3047218822Sdim return symbol_relc_make_value (exp->X_add_number); 3048218822Sdim 3049218822Sdim case O_symbol: 3050218822Sdim if (exp->X_add_number) 3051218822Sdim { 3052218822Sdim arity = 2; 3053218822Sdim opstr = "+"; 3054218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); 3055218822Sdim operands[1] = symbol_relc_make_value (exp->X_add_number); 3056218822Sdim break; 3057218822Sdim } 3058218822Sdim else 3059218822Sdim return symbol_relc_make_sym (exp->X_add_symbol); 3060218822Sdim 3061218822Sdim /* Helper macros for nesting nodes. */ 3062218822Sdim 3063218822Sdim#define HANDLE_XADD_OPT1(str_) \ 3064218822Sdim if (exp->X_add_number) \ 3065218822Sdim { \ 3066218822Sdim arity = 2; \ 3067218822Sdim opstr = "+:" str_; \ 3068218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3069218822Sdim operands[1] = symbol_relc_make_value (exp->X_add_number); \ 3070218822Sdim break; \ 3071218822Sdim } \ 3072218822Sdim else \ 3073218822Sdim { \ 3074218822Sdim arity = 1; \ 3075218822Sdim opstr = str_; \ 3076218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3077218822Sdim } \ 3078218822Sdim break 3079218822Sdim 3080218822Sdim#define HANDLE_XADD_OPT2(str_) \ 3081218822Sdim if (exp->X_add_number) \ 3082218822Sdim { \ 3083218822Sdim arity = 3; \ 3084218822Sdim opstr = "+:" str_; \ 3085218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3086218822Sdim operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \ 3087218822Sdim operands[2] = symbol_relc_make_value (exp->X_add_number); \ 3088218822Sdim } \ 3089218822Sdim else \ 3090218822Sdim { \ 3091218822Sdim arity = 2; \ 3092218822Sdim opstr = str_; \ 3093218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3094218822Sdim operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \ 3095218822Sdim } \ 3096218822Sdim break 3097218822Sdim 3098218822Sdim /* Nesting nodes. */ 3099218822Sdim 3100218822Sdim case O_uminus: HANDLE_XADD_OPT1 ("0-"); 3101218822Sdim case O_bit_not: HANDLE_XADD_OPT1 ("~"); 3102218822Sdim case O_logical_not: HANDLE_XADD_OPT1 ("!"); 3103218822Sdim case O_multiply: HANDLE_XADD_OPT2 ("*"); 3104218822Sdim case O_divide: HANDLE_XADD_OPT2 ("/"); 3105218822Sdim case O_modulus: HANDLE_XADD_OPT2 ("%"); 3106218822Sdim case O_left_shift: HANDLE_XADD_OPT2 ("<<"); 3107218822Sdim case O_right_shift: HANDLE_XADD_OPT2 (">>"); 3108218822Sdim case O_bit_inclusive_or: HANDLE_XADD_OPT2 ("|"); 3109218822Sdim case O_bit_exclusive_or: HANDLE_XADD_OPT2 ("^"); 3110218822Sdim case O_bit_and: HANDLE_XADD_OPT2 ("&"); 3111218822Sdim case O_add: HANDLE_XADD_OPT2 ("+"); 3112218822Sdim case O_subtract: HANDLE_XADD_OPT2 ("-"); 3113218822Sdim case O_eq: HANDLE_XADD_OPT2 ("=="); 3114218822Sdim case O_ne: HANDLE_XADD_OPT2 ("!="); 3115218822Sdim case O_lt: HANDLE_XADD_OPT2 ("<"); 3116218822Sdim case O_le: HANDLE_XADD_OPT2 ("<="); 3117218822Sdim case O_ge: HANDLE_XADD_OPT2 (">="); 3118218822Sdim case O_gt: HANDLE_XADD_OPT2 (">"); 3119218822Sdim case O_logical_and: HANDLE_XADD_OPT2 ("&&"); 3120218822Sdim case O_logical_or: HANDLE_XADD_OPT2 ("||"); 3121218822Sdim } 3122218822Sdim 3123218822Sdim /* Validate & reject early. */ 3124218822Sdim if (arity >= 1 && ((operands[0] == NULL) || (strlen (operands[0]) == 0))) 3125218822Sdim opstr = NULL; 3126218822Sdim if (arity >= 2 && ((operands[1] == NULL) || (strlen (operands[1]) == 0))) 3127218822Sdim opstr = NULL; 3128218822Sdim if (arity >= 3 && ((operands[2] == NULL) || (strlen (operands[2]) == 0))) 3129218822Sdim opstr = NULL; 3130218822Sdim 3131218822Sdim if (opstr == NULL) 3132218822Sdim concat_string = NULL; 3133218822Sdim else 3134218822Sdim { 3135218822Sdim /* Allocate new string; include inter-operand padding gaps etc. */ 3136218822Sdim concat_string = xmalloc (strlen (opstr) 3137218822Sdim + 1 3138218822Sdim + (arity >= 1 ? (strlen (operands[0]) + 1 ) : 0) 3139218822Sdim + (arity >= 2 ? (strlen (operands[1]) + 1 ) : 0) 3140218822Sdim + (arity >= 3 ? (strlen (operands[2]) + 0 ) : 0) 3141218822Sdim + 1); 3142218822Sdim assert (concat_string != NULL); 3143218822Sdim 3144218822Sdim /* Format the thing. */ 3145218822Sdim sprintf (concat_string, 3146218822Sdim (arity == 0 ? "%s" : 3147218822Sdim arity == 1 ? "%s:%s" : 3148218822Sdim arity == 2 ? "%s:%s:%s" : 3149218822Sdim /* arity == 3 */ "%s:%s:%s:%s"), 3150218822Sdim opstr, operands[0], operands[1], operands[2]); 3151218822Sdim } 3152218822Sdim 3153218822Sdim /* Free operand strings (not opstr). */ 3154218822Sdim if (arity >= 1) xfree (operands[0]); 3155218822Sdim if (arity >= 2) xfree (operands[1]); 3156218822Sdim if (arity >= 3) xfree (operands[2]); 3157218822Sdim 3158218822Sdim return concat_string; 3159218822Sdim} 3160218822Sdim 316160484Sobrien#endif 3162