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 } 166933965Sjdp while ((*p++ = *--q) != '\0');; 167033965Sjdp 167177298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 167233965Sjdp return symbol_name_build; 167333965Sjdp} 167433965Sjdp 1675130561Sobrien/* Somebody else's idea of local labels. They are made by "n:" where n 167677298Sobrien is any decimal digit. Refer to them with 167777298Sobrien "nb" for previous (backward) n: 167877298Sobrien or "nf" for next (forward) n:. 167933965Sjdp 168077298Sobrien We do a little better and let n be any number, not just a single digit, but 168177298Sobrien since the other guy's assembler only does ten, we treat the first ten 168277298Sobrien specially. 168377298Sobrien 168477298Sobrien Like someone else's assembler, we have one set of local label counters for 168577298Sobrien entire assembly, not one set per (sub)segment like in most assemblers. This 168677298Sobrien implies that one can refer to a label in another segment, and indeed some 168777298Sobrien crufty compilers have done just that. 168877298Sobrien 168977298Sobrien Since there could be a LOT of these things, treat them as a sparse 169077298Sobrien array. */ 169177298Sobrien 169233965Sjdp#define FB_LABEL_SPECIAL (10) 169333965Sjdp 169433965Sjdpstatic long fb_low_counter[FB_LABEL_SPECIAL]; 169533965Sjdpstatic long *fb_labels; 169633965Sjdpstatic long *fb_label_instances; 169733965Sjdpstatic long fb_label_count; 169833965Sjdpstatic long fb_label_max; 169933965Sjdp 170077298Sobrien/* This must be more than FB_LABEL_SPECIAL. */ 170133965Sjdp#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6) 170233965Sjdp 170377298Sobrienstatic void 1704130561Sobrienfb_label_init (void) 170533965Sjdp{ 170633965Sjdp memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter)); 170777298Sobrien} 170833965Sjdp 170977298Sobrien/* Add one to the instance number of this fb label. */ 171077298Sobrien 171177298Sobrienvoid 1712130561Sobrienfb_label_instance_inc (long label) 171333965Sjdp{ 171433965Sjdp long *i; 171533965Sjdp 171633965Sjdp if (label < FB_LABEL_SPECIAL) 171733965Sjdp { 171833965Sjdp ++fb_low_counter[label]; 171933965Sjdp return; 172033965Sjdp } 172133965Sjdp 172233965Sjdp if (fb_labels != NULL) 172333965Sjdp { 172433965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 172533965Sjdp i < fb_labels + fb_label_count; ++i) 172633965Sjdp { 172733965Sjdp if (*i == label) 172833965Sjdp { 172933965Sjdp ++fb_label_instances[i - fb_labels]; 173033965Sjdp return; 173177298Sobrien } /* if we find it */ 173277298Sobrien } /* for each existing label */ 173333965Sjdp } 173433965Sjdp 173577298Sobrien /* If we get to here, we don't have label listed yet. */ 173633965Sjdp 173733965Sjdp if (fb_labels == NULL) 173833965Sjdp { 173933965Sjdp fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 174033965Sjdp fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long)); 174133965Sjdp fb_label_max = FB_LABEL_BUMP_BY; 174233965Sjdp fb_label_count = FB_LABEL_SPECIAL; 174333965Sjdp 174433965Sjdp } 174533965Sjdp else if (fb_label_count == fb_label_max) 174633965Sjdp { 174733965Sjdp fb_label_max += FB_LABEL_BUMP_BY; 174833965Sjdp fb_labels = (long *) xrealloc ((char *) fb_labels, 174933965Sjdp fb_label_max * sizeof (long)); 175033965Sjdp fb_label_instances = (long *) xrealloc ((char *) fb_label_instances, 175133965Sjdp fb_label_max * sizeof (long)); 175277298Sobrien } /* if we needed to grow */ 175333965Sjdp 175433965Sjdp fb_labels[fb_label_count] = label; 175533965Sjdp fb_label_instances[fb_label_count] = 1; 175633965Sjdp ++fb_label_count; 175733965Sjdp} 175833965Sjdp 175977298Sobrienstatic long 1760130561Sobrienfb_label_instance (long label) 176133965Sjdp{ 176233965Sjdp long *i; 176333965Sjdp 176433965Sjdp if (label < FB_LABEL_SPECIAL) 176533965Sjdp { 176633965Sjdp return (fb_low_counter[label]); 176733965Sjdp } 176833965Sjdp 176933965Sjdp if (fb_labels != NULL) 177033965Sjdp { 177133965Sjdp for (i = fb_labels + FB_LABEL_SPECIAL; 177233965Sjdp i < fb_labels + fb_label_count; ++i) 177333965Sjdp { 177433965Sjdp if (*i == label) 177533965Sjdp { 177633965Sjdp return (fb_label_instances[i - fb_labels]); 177777298Sobrien } /* if we find it */ 177877298Sobrien } /* for each existing label */ 177933965Sjdp } 178033965Sjdp 178133965Sjdp /* We didn't find the label, so this must be a reference to the 178233965Sjdp first instance. */ 178333965Sjdp return 0; 178433965Sjdp} 178533965Sjdp 178677298Sobrien/* Caller must copy returned name: we re-use the area for the next name. 178733965Sjdp 178877298Sobrien The mth occurence of label n: is turned into the symbol "Ln^Bm" 178977298Sobrien where n is the label number and m is the instance number. "L" makes 179077298Sobrien it a label discarded unless debugging and "^B"('\2') ensures no 179177298Sobrien ordinary symbol SHOULD get the same name as a local label 179277298Sobrien symbol. The first "4:" is "L4^B1" - the m numbers begin at 1. 179377298Sobrien 179477298Sobrien dollar labels get the same treatment, except that ^A is used in 179577298Sobrien place of ^B. */ 179677298Sobrien 179777298Sobrienchar * /* Return local label name. */ 1798130561Sobrienfb_label_name (long n, /* We just saw "n:", "nf" or "nb" : n a number. */ 1799130561Sobrien long augend /* 0 for nb, 1 for n:, nf. */) 180033965Sjdp{ 180133965Sjdp long i; 180277298Sobrien /* Returned to caller, then copied. Used for created names ("4f"). */ 180333965Sjdp static char symbol_name_build[24]; 180433965Sjdp register char *p; 180533965Sjdp register char *q; 180677298Sobrien char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */ 180733965Sjdp 180833965Sjdp know (n >= 0); 1809218822Sdim#ifdef TC_MMIX 1810218822Sdim know ((unsigned long) augend <= 2 /* See mmix_fb_label. */); 1811218822Sdim#else 1812218822Sdim know ((unsigned long) augend <= 1); 1813218822Sdim#endif 181433965Sjdp p = symbol_name_build; 181577298Sobrien#ifdef LOCAL_LABEL_PREFIX 181677298Sobrien *p++ = LOCAL_LABEL_PREFIX; 181777298Sobrien#endif 181833965Sjdp *p++ = 'L'; 181933965Sjdp 182077298Sobrien /* Next code just does sprintf( {}, "%d", n); */ 182177298Sobrien /* Label number. */ 182233965Sjdp q = symbol_name_temporary; 182333965Sjdp for (*q++ = 0, i = n; i; ++q) 182433965Sjdp { 182533965Sjdp *q = i % 10 + '0'; 182633965Sjdp i /= 10; 182733965Sjdp } 182833965Sjdp while ((*p = *--q) != '\0') 182933965Sjdp ++p; 183033965Sjdp 183177298Sobrien *p++ = LOCAL_LABEL_CHAR; /* ^B */ 183233965Sjdp 183377298Sobrien /* Instance number. */ 183433965Sjdp q = symbol_name_temporary; 183533965Sjdp for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q) 183633965Sjdp { 183733965Sjdp *q = i % 10 + '0'; 183833965Sjdp i /= 10; 183933965Sjdp } 184033965Sjdp while ((*p++ = *--q) != '\0');; 184133965Sjdp 184277298Sobrien /* The label, as a '\0' ended string, starts at symbol_name_build. */ 184333965Sjdp return (symbol_name_build); 184477298Sobrien} 184533965Sjdp 184677298Sobrien/* Decode name that may have been generated by foo_label_name() above. 184777298Sobrien If the name wasn't generated by foo_label_name(), then return it 184877298Sobrien unaltered. This is used for error messages. */ 184933965Sjdp 185033965Sjdpchar * 1851130561Sobriendecode_local_label_name (char *s) 185233965Sjdp{ 185333965Sjdp char *p; 185433965Sjdp char *symbol_decode; 185533965Sjdp int label_number; 185633965Sjdp int instance_number; 185733965Sjdp char *type; 185878828Sobrien const char *message_format; 185977298Sobrien int index = 0; 186033965Sjdp 186177298Sobrien#ifdef LOCAL_LABEL_PREFIX 186277298Sobrien if (s[index] == LOCAL_LABEL_PREFIX) 186377298Sobrien ++index; 186477298Sobrien#endif 186577298Sobrien 186677298Sobrien if (s[index] != 'L') 186733965Sjdp return s; 186833965Sjdp 186989857Sobrien for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p) 187033965Sjdp label_number = (10 * label_number) + *p - '0'; 187133965Sjdp 187277298Sobrien if (*p == DOLLAR_LABEL_CHAR) 187333965Sjdp type = "dollar"; 187477298Sobrien else if (*p == LOCAL_LABEL_CHAR) 187533965Sjdp type = "fb"; 187633965Sjdp else 187733965Sjdp return s; 187833965Sjdp 187989857Sobrien for (instance_number = 0, p++; ISDIGIT (*p); ++p) 188033965Sjdp instance_number = (10 * instance_number) + *p - '0'; 188133965Sjdp 188278828Sobrien message_format = _("\"%d\" (instance number %d of a %s label)"); 188333965Sjdp symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30); 188433965Sjdp sprintf (symbol_decode, message_format, label_number, instance_number, type); 188533965Sjdp 188633965Sjdp return symbol_decode; 188733965Sjdp} 188833965Sjdp 188933965Sjdp/* Get the value of a symbol. */ 189033965Sjdp 189133965SjdpvalueT 1892130561SobrienS_GET_VALUE (symbolS *s) 189333965Sjdp{ 189460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 189589857Sobrien return resolve_symbol_value (s); 189660484Sobrien 189789857Sobrien if (!s->sy_resolved) 189889857Sobrien { 189989857Sobrien valueT val = resolve_symbol_value (s); 190089857Sobrien if (!finalize_syms) 190189857Sobrien return val; 190289857Sobrien } 1903218822Sdim if (S_IS_WEAKREFR (s)) 1904218822Sdim return S_GET_VALUE (s->sy_value.X_add_symbol); 1905218822Sdim 190633965Sjdp if (s->sy_value.X_op != O_constant) 190733965Sjdp { 190833965Sjdp if (! s->sy_resolved 190933965Sjdp || s->sy_value.X_op != O_symbol 191033965Sjdp || (S_IS_DEFINED (s) && ! S_IS_COMMON (s))) 191189857Sobrien as_bad (_("attempt to get value of unresolved symbol `%s'"), 191233965Sjdp S_GET_NAME (s)); 191333965Sjdp } 191433965Sjdp return (valueT) s->sy_value.X_add_number; 191533965Sjdp} 191633965Sjdp 191733965Sjdp/* Set the value of a symbol. */ 191833965Sjdp 191933965Sjdpvoid 1920130561SobrienS_SET_VALUE (symbolS *s, valueT val) 192133965Sjdp{ 192260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 192360484Sobrien { 192489857Sobrien ((struct local_symbol *) s)->lsy_value = val; 192560484Sobrien return; 192660484Sobrien } 192760484Sobrien 192833965Sjdp s->sy_value.X_op = O_constant; 192933965Sjdp s->sy_value.X_add_number = (offsetT) val; 193033965Sjdp s->sy_value.X_unsigned = 0; 1931218822Sdim S_CLEAR_WEAKREFR (s); 193233965Sjdp} 193333965Sjdp 193433965Sjdpvoid 1935130561Sobriencopy_symbol_attributes (symbolS *dest, symbolS *src) 193633965Sjdp{ 193760484Sobrien if (LOCAL_SYMBOL_CHECK (dest)) 193860484Sobrien dest = local_symbol_convert ((struct local_symbol *) dest); 193960484Sobrien if (LOCAL_SYMBOL_CHECK (src)) 194060484Sobrien src = local_symbol_convert ((struct local_symbol *) src); 194160484Sobrien 194233965Sjdp /* In an expression, transfer the settings of these flags. 194333965Sjdp The user can override later, of course. */ 194438889Sjdp#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT) 194533965Sjdp dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS; 194633965Sjdp 194733965Sjdp#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES 194833965Sjdp OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); 194933965Sjdp#endif 1950218822Sdim 1951218822Sdim#ifdef TC_COPY_SYMBOL_ATTRIBUTES 1952218822Sdim TC_COPY_SYMBOL_ATTRIBUTES (dest, src); 1953218822Sdim#endif 195433965Sjdp} 195533965Sjdp 195633965Sjdpint 1957130561SobrienS_IS_FUNCTION (symbolS *s) 195860484Sobrien{ 195960484Sobrien flagword flags; 196060484Sobrien 196160484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 196260484Sobrien return 0; 196360484Sobrien 196460484Sobrien flags = s->bsym->flags; 196560484Sobrien 196660484Sobrien return (flags & BSF_FUNCTION) != 0; 196760484Sobrien} 196860484Sobrien 196960484Sobrienint 1970130561SobrienS_IS_EXTERNAL (symbolS *s) 197133965Sjdp{ 197260484Sobrien flagword flags; 197333965Sjdp 197460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 197560484Sobrien return 0; 197660484Sobrien 197760484Sobrien flags = s->bsym->flags; 197860484Sobrien 197977298Sobrien /* Sanity check. */ 198038889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 198133965Sjdp abort (); 198233965Sjdp 198333965Sjdp return (flags & BSF_GLOBAL) != 0; 198433965Sjdp} 198533965Sjdp 198633965Sjdpint 1987130561SobrienS_IS_WEAK (symbolS *s) 198833965Sjdp{ 198960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 199060484Sobrien return 0; 1991218822Sdim /* Conceptually, a weakrefr is weak if the referenced symbol is. We 1992218822Sdim could probably handle a WEAKREFR as always weak though. E.g., if 1993218822Sdim the referenced symbol has lost its weak status, there's no reason 1994218822Sdim to keep handling the weakrefr as if it was weak. */ 1995218822Sdim if (S_IS_WEAKREFR (s)) 1996218822Sdim return S_IS_WEAK (s->sy_value.X_add_symbol); 199733965Sjdp return (s->bsym->flags & BSF_WEAK) != 0; 199833965Sjdp} 199933965Sjdp 200033965Sjdpint 2001218822SdimS_IS_WEAKREFR (symbolS *s) 2002218822Sdim{ 2003218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2004218822Sdim return 0; 2005218822Sdim return s->sy_weakrefr != 0; 2006218822Sdim} 2007218822Sdim 2008218822Sdimint 2009218822SdimS_IS_WEAKREFD (symbolS *s) 2010218822Sdim{ 2011218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2012218822Sdim return 0; 2013218822Sdim return s->sy_weakrefd != 0; 2014218822Sdim} 2015218822Sdim 2016218822Sdimint 2017130561SobrienS_IS_COMMON (symbolS *s) 201833965Sjdp{ 201960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202060484Sobrien return 0; 202133965Sjdp return bfd_is_com_section (s->bsym->section); 202233965Sjdp} 202333965Sjdp 202433965Sjdpint 2025130561SobrienS_IS_DEFINED (symbolS *s) 202633965Sjdp{ 202760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 202860484Sobrien return ((struct local_symbol *) s)->lsy_section != undefined_section; 202933965Sjdp return s->bsym->section != undefined_section; 203033965Sjdp} 203133965Sjdp 2032130561Sobrien 2033130561Sobrien#ifndef EXTERN_FORCE_RELOC 2034130561Sobrien#define EXTERN_FORCE_RELOC IS_ELF 2035130561Sobrien#endif 2036130561Sobrien 2037130561Sobrien/* Return true for symbols that should not be reduced to section 2038130561Sobrien symbols or eliminated from expressions, because they may be 2039130561Sobrien overridden by the linker. */ 204033965Sjdpint 2041130561SobrienS_FORCE_RELOC (symbolS *s, int strict) 204233965Sjdp{ 204360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 2044130561Sobrien return ((struct local_symbol *) s)->lsy_section == undefined_section; 2045130561Sobrien 2046130561Sobrien return ((strict 2047130561Sobrien && ((s->bsym->flags & BSF_WEAK) != 0 2048130561Sobrien || (EXTERN_FORCE_RELOC 2049130561Sobrien && (s->bsym->flags & BSF_GLOBAL) != 0))) 2050130561Sobrien || s->bsym->section == undefined_section 2051130561Sobrien || bfd_is_com_section (s->bsym->section)); 2052130561Sobrien} 2053130561Sobrien 2054130561Sobrienint 2055130561SobrienS_IS_DEBUG (symbolS *s) 2056130561Sobrien{ 2057130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 205860484Sobrien return 0; 205933965Sjdp if (s->bsym->flags & BSF_DEBUGGING) 206033965Sjdp return 1; 206133965Sjdp return 0; 206233965Sjdp} 206333965Sjdp 206433965Sjdpint 2065130561SobrienS_IS_LOCAL (symbolS *s) 206633965Sjdp{ 206760484Sobrien flagword flags; 206833965Sjdp const char *name; 206933965Sjdp 207060484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 207160484Sobrien return 1; 207260484Sobrien 207360484Sobrien flags = s->bsym->flags; 207460484Sobrien 207577298Sobrien /* Sanity check. */ 207638889Sjdp if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) 207733965Sjdp abort (); 207833965Sjdp 207933965Sjdp if (bfd_get_section (s->bsym) == reg_section) 208033965Sjdp return 1; 208133965Sjdp 208238889Sjdp if (flag_strip_local_absolute 2083218822Sdim /* Keep BSF_FILE symbols in order to allow debuggers to identify 2084218822Sdim the source file even when the object file is stripped. */ 2085218822Sdim && (flags & (BSF_GLOBAL | BSF_FILE)) == 0 208638889Sjdp && bfd_get_section (s->bsym) == absolute_section) 208738889Sjdp return 1; 208838889Sjdp 208933965Sjdp name = S_GET_NAME (s); 209033965Sjdp return (name != NULL 209133965Sjdp && ! S_IS_DEBUG (s) 209277298Sobrien && (strchr (name, DOLLAR_LABEL_CHAR) 209377298Sobrien || strchr (name, LOCAL_LABEL_CHAR) 209433965Sjdp || (! flag_keep_locals 209533965Sjdp && (bfd_is_local_label (stdoutput, s->bsym) 209633965Sjdp || (flag_mri 209733965Sjdp && name[0] == '?' 209833965Sjdp && name[1] == '?'))))); 209933965Sjdp} 210033965Sjdp 210133965Sjdpint 2102218822SdimS_IS_STABD (symbolS *s) 210333965Sjdp{ 2104218822Sdim return S_GET_NAME (s) == 0; 210533965Sjdp} 210633965Sjdp 210733965Sjdpint 2108218822SdimS_IS_VOLATILE (const symbolS *s) 210933965Sjdp{ 2110218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2111218822Sdim return 0; 2112218822Sdim return s->sy_volatile; 211333965Sjdp} 211433965Sjdp 2115218822Sdimint 2116218822SdimS_IS_FORWARD_REF (const symbolS *s) 2117218822Sdim{ 2118218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2119218822Sdim return 0; 2120218822Sdim return s->sy_forward_ref; 2121218822Sdim} 2122218822Sdim 2123104834Sobrienconst char * 2124130561SobrienS_GET_NAME (symbolS *s) 212533965Sjdp{ 212660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 212760484Sobrien return ((struct local_symbol *) s)->lsy_name; 212833965Sjdp return s->bsym->name; 212933965Sjdp} 213033965Sjdp 213133965SjdpsegT 2132130561SobrienS_GET_SEGMENT (symbolS *s) 213333965Sjdp{ 213460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 213560484Sobrien return ((struct local_symbol *) s)->lsy_section; 213633965Sjdp return s->bsym->section; 213733965Sjdp} 213833965Sjdp 213933965Sjdpvoid 2140130561SobrienS_SET_SEGMENT (symbolS *s, segT seg) 214133965Sjdp{ 214238889Sjdp /* Don't reassign section symbols. The direct reason is to prevent seg 214338889Sjdp faults assigning back to const global symbols such as *ABS*, but it 214438889Sjdp shouldn't happen anyway. */ 214538889Sjdp 214660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 214760484Sobrien { 214860484Sobrien if (seg == reg_section) 214960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 215060484Sobrien else 215160484Sobrien { 215260484Sobrien ((struct local_symbol *) s)->lsy_section = seg; 215360484Sobrien return; 215460484Sobrien } 215560484Sobrien } 215660484Sobrien 215738889Sjdp if (s->bsym->flags & BSF_SECTION_SYM) 215838889Sjdp { 215938889Sjdp if (s->bsym->section != seg) 216077298Sobrien abort (); 216138889Sjdp } 216238889Sjdp else 216338889Sjdp s->bsym->section = seg; 216433965Sjdp} 216533965Sjdp 216633965Sjdpvoid 2167130561SobrienS_SET_EXTERNAL (symbolS *s) 216833965Sjdp{ 216960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 217060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 217133965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 217233965Sjdp { 217333965Sjdp /* Let .weak override .global. */ 217433965Sjdp return; 217533965Sjdp } 217678828Sobrien if (s->bsym->flags & BSF_SECTION_SYM) 217778828Sobrien { 217878828Sobrien char * file; 217978828Sobrien unsigned int line; 2180104834Sobrien 218178828Sobrien /* Do not reassign section symbols. */ 218278828Sobrien as_where (& file, & line); 218378828Sobrien as_warn_where (file, line, 218489857Sobrien _("section symbols are already global")); 218578828Sobrien return; 218678828Sobrien } 218733965Sjdp s->bsym->flags |= BSF_GLOBAL; 218877298Sobrien s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); 2189218822Sdim 2190218822Sdim#ifdef USE_UNIQUE 2191218822Sdim if (! an_external_name && S_GET_NAME(s)[0] != '.') 2192218822Sdim an_external_name = S_GET_NAME (s); 2193218822Sdim#endif 219433965Sjdp} 219533965Sjdp 219633965Sjdpvoid 2197130561SobrienS_CLEAR_EXTERNAL (symbolS *s) 219833965Sjdp{ 219960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 220060484Sobrien return; 220133965Sjdp if ((s->bsym->flags & BSF_WEAK) != 0) 220233965Sjdp { 220333965Sjdp /* Let .weak override. */ 220433965Sjdp return; 220533965Sjdp } 220633965Sjdp s->bsym->flags |= BSF_LOCAL; 220777298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); 220833965Sjdp} 220933965Sjdp 221033965Sjdpvoid 2211130561SobrienS_SET_WEAK (symbolS *s) 221233965Sjdp{ 221360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 221460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2215218822Sdim#ifdef obj_set_weak_hook 2216218822Sdim obj_set_weak_hook (s); 2217218822Sdim#endif 221833965Sjdp s->bsym->flags |= BSF_WEAK; 221977298Sobrien s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); 222033965Sjdp} 222133965Sjdp 222233965Sjdpvoid 2223218822SdimS_SET_WEAKREFR (symbolS *s) 2224218822Sdim{ 2225218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2226218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2227218822Sdim s->sy_weakrefr = 1; 2228218822Sdim /* If the alias was already used, make sure we mark the target as 2229218822Sdim used as well, otherwise it might be dropped from the symbol 2230218822Sdim table. This may have unintended side effects if the alias is 2231218822Sdim later redirected to another symbol, such as keeping the unused 2232218822Sdim previous target in the symbol table. Since it will be weak, it's 2233218822Sdim not a big deal. */ 2234218822Sdim if (s->sy_used) 2235218822Sdim symbol_mark_used (s->sy_value.X_add_symbol); 2236218822Sdim} 2237218822Sdim 2238218822Sdimvoid 2239218822SdimS_CLEAR_WEAKREFR (symbolS *s) 2240218822Sdim{ 2241218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2242218822Sdim return; 2243218822Sdim s->sy_weakrefr = 0; 2244218822Sdim} 2245218822Sdim 2246218822Sdimvoid 2247218822SdimS_SET_WEAKREFD (symbolS *s) 2248218822Sdim{ 2249218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2250218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2251218822Sdim s->sy_weakrefd = 1; 2252218822Sdim S_SET_WEAK (s); 2253218822Sdim} 2254218822Sdim 2255218822Sdimvoid 2256218822SdimS_CLEAR_WEAKREFD (symbolS *s) 2257218822Sdim{ 2258218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2259218822Sdim return; 2260218822Sdim if (s->sy_weakrefd) 2261218822Sdim { 2262218822Sdim s->sy_weakrefd = 0; 2263218822Sdim /* If a weakref target symbol is weak, then it was never 2264218822Sdim referenced directly before, not even in a .global directive, 2265218822Sdim so decay it to local. If it remains undefined, it will be 2266218822Sdim later turned into a global, like any other undefined 2267218822Sdim symbol. */ 2268218822Sdim if (s->bsym->flags & BSF_WEAK) 2269218822Sdim { 2270218822Sdim#ifdef obj_clear_weak_hook 2271218822Sdim obj_clear_weak_hook (s); 2272218822Sdim#endif 2273218822Sdim s->bsym->flags &= ~BSF_WEAK; 2274218822Sdim s->bsym->flags |= BSF_LOCAL; 2275218822Sdim } 2276218822Sdim } 2277218822Sdim} 2278218822Sdim 2279218822Sdimvoid 2280130561SobrienS_SET_THREAD_LOCAL (symbolS *s) 228133965Sjdp{ 228260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 2283130561Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2284130561Sobrien if (bfd_is_com_section (s->bsym->section) 2285130561Sobrien && (s->bsym->flags & BSF_THREAD_LOCAL) != 0) 2286130561Sobrien return; 2287130561Sobrien s->bsym->flags |= BSF_THREAD_LOCAL; 2288130561Sobrien if ((s->bsym->flags & BSF_FUNCTION) != 0) 2289130561Sobrien as_bad (_("Accessing function `%s' as thread-local object"), 2290130561Sobrien S_GET_NAME (s)); 2291130561Sobrien else if (! bfd_is_und_section (s->bsym->section) 2292130561Sobrien && (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0) 2293130561Sobrien as_bad (_("Accessing `%s' as thread-local object"), 2294130561Sobrien S_GET_NAME (s)); 2295130561Sobrien} 2296130561Sobrien 2297130561Sobrienvoid 2298218822SdimS_SET_NAME (symbolS *s, const char *name) 2299130561Sobrien{ 2300130561Sobrien if (LOCAL_SYMBOL_CHECK (s)) 230160484Sobrien { 230260484Sobrien ((struct local_symbol *) s)->lsy_name = name; 230360484Sobrien return; 230460484Sobrien } 230533965Sjdp s->bsym->name = name; 230633965Sjdp} 230733965Sjdp 2308218822Sdimvoid 2309218822SdimS_SET_VOLATILE (symbolS *s) 2310218822Sdim{ 2311218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2312218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2313218822Sdim s->sy_volatile = 1; 2314218822Sdim} 231560484Sobrien 2316218822Sdimvoid 2317218822SdimS_CLEAR_VOLATILE (symbolS *s) 2318218822Sdim{ 2319218822Sdim if (!LOCAL_SYMBOL_CHECK (s)) 2320218822Sdim s->sy_volatile = 0; 2321218822Sdim} 2322218822Sdim 2323218822Sdimvoid 2324218822SdimS_SET_FORWARD_REF (symbolS *s) 2325218822Sdim{ 2326218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2327218822Sdim s = local_symbol_convert ((struct local_symbol *) s); 2328218822Sdim s->sy_forward_ref = 1; 2329218822Sdim} 2330218822Sdim 233160484Sobrien/* Return the previous symbol in a chain. */ 233260484Sobrien 233360484SobriensymbolS * 2334130561Sobriensymbol_previous (symbolS *s) 233560484Sobrien{ 233660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 233760484Sobrien abort (); 233860484Sobrien return s->sy_previous; 233960484Sobrien} 234060484Sobrien 234160484Sobrien/* Return the next symbol in a chain. */ 234260484Sobrien 234360484SobriensymbolS * 2344130561Sobriensymbol_next (symbolS *s) 234560484Sobrien{ 234660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 234760484Sobrien abort (); 234860484Sobrien return s->sy_next; 234960484Sobrien} 235060484Sobrien 235160484Sobrien/* Return a pointer to the value of a symbol as an expression. */ 235260484Sobrien 235360484SobrienexpressionS * 2354130561Sobriensymbol_get_value_expression (symbolS *s) 235560484Sobrien{ 235660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 235760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 235860484Sobrien return &s->sy_value; 235960484Sobrien} 236060484Sobrien 236160484Sobrien/* Set the value of a symbol to an expression. */ 236260484Sobrien 236333965Sjdpvoid 2364130561Sobriensymbol_set_value_expression (symbolS *s, const expressionS *exp) 236560484Sobrien{ 236660484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 236760484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 236860484Sobrien s->sy_value = *exp; 2369218822Sdim S_CLEAR_WEAKREFR (s); 237060484Sobrien} 237160484Sobrien 2372218822Sdim/* Return a pointer to the X_add_number component of a symbol. */ 2373218822Sdim 2374218822SdimoffsetT * 2375218822Sdimsymbol_X_add_number (symbolS *s) 2376218822Sdim{ 2377218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2378218822Sdim return (offsetT *) &((struct local_symbol *) s)->lsy_value; 2379218822Sdim 2380218822Sdim return &s->sy_value.X_add_number; 2381218822Sdim} 2382218822Sdim 2383130561Sobrien/* Set the value of SYM to the current position in the current segment. */ 2384130561Sobrien 2385130561Sobrienvoid 2386130561Sobriensymbol_set_value_now (symbolS *sym) 2387130561Sobrien{ 2388130561Sobrien S_SET_SEGMENT (sym, now_seg); 2389130561Sobrien S_SET_VALUE (sym, frag_now_fix ()); 2390130561Sobrien symbol_set_frag (sym, frag_now); 2391130561Sobrien} 2392130561Sobrien 239360484Sobrien/* Set the frag of a symbol. */ 239460484Sobrien 239560484Sobrienvoid 2396130561Sobriensymbol_set_frag (symbolS *s, fragS *f) 239760484Sobrien{ 239860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 239960484Sobrien { 240060484Sobrien local_symbol_set_frag ((struct local_symbol *) s, f); 240160484Sobrien return; 240260484Sobrien } 240360484Sobrien s->sy_frag = f; 2404218822Sdim S_CLEAR_WEAKREFR (s); 240560484Sobrien} 240660484Sobrien 240760484Sobrien/* Return the frag of a symbol. */ 240860484Sobrien 240960484SobrienfragS * 2410130561Sobriensymbol_get_frag (symbolS *s) 241160484Sobrien{ 241260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 241360484Sobrien return local_symbol_get_frag ((struct local_symbol *) s); 241460484Sobrien return s->sy_frag; 241560484Sobrien} 241660484Sobrien 241760484Sobrien/* Mark a symbol as having been used. */ 241860484Sobrien 241960484Sobrienvoid 2420130561Sobriensymbol_mark_used (symbolS *s) 242160484Sobrien{ 242260484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 242360484Sobrien return; 242460484Sobrien s->sy_used = 1; 2425218822Sdim if (S_IS_WEAKREFR (s)) 2426218822Sdim symbol_mark_used (s->sy_value.X_add_symbol); 242760484Sobrien} 242860484Sobrien 242960484Sobrien/* Clear the mark of whether a symbol has been used. */ 243060484Sobrien 243160484Sobrienvoid 2432130561Sobriensymbol_clear_used (symbolS *s) 243360484Sobrien{ 243460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 243560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 243660484Sobrien s->sy_used = 0; 243760484Sobrien} 243860484Sobrien 243960484Sobrien/* Return whether a symbol has been used. */ 244060484Sobrien 244160484Sobrienint 2442130561Sobriensymbol_used_p (symbolS *s) 244360484Sobrien{ 244460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 244560484Sobrien return 1; 244660484Sobrien return s->sy_used; 244760484Sobrien} 244860484Sobrien 244960484Sobrien/* Mark a symbol as having been used in a reloc. */ 245060484Sobrien 245160484Sobrienvoid 2452130561Sobriensymbol_mark_used_in_reloc (symbolS *s) 245360484Sobrien{ 245460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 245560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 245660484Sobrien s->sy_used_in_reloc = 1; 245760484Sobrien} 245860484Sobrien 245960484Sobrien/* Clear the mark of whether a symbol has been used in a reloc. */ 246060484Sobrien 246160484Sobrienvoid 2462130561Sobriensymbol_clear_used_in_reloc (symbolS *s) 246360484Sobrien{ 246460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 246560484Sobrien return; 246660484Sobrien s->sy_used_in_reloc = 0; 246760484Sobrien} 246860484Sobrien 246960484Sobrien/* Return whether a symbol has been used in a reloc. */ 247060484Sobrien 247160484Sobrienint 2472130561Sobriensymbol_used_in_reloc_p (symbolS *s) 247360484Sobrien{ 247460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 247560484Sobrien return 0; 247660484Sobrien return s->sy_used_in_reloc; 247760484Sobrien} 247860484Sobrien 247960484Sobrien/* Mark a symbol as an MRI common symbol. */ 248060484Sobrien 248160484Sobrienvoid 2482130561Sobriensymbol_mark_mri_common (symbolS *s) 248360484Sobrien{ 248460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 248560484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 248660484Sobrien s->sy_mri_common = 1; 248760484Sobrien} 248860484Sobrien 248960484Sobrien/* Clear the mark of whether a symbol is an MRI common symbol. */ 249060484Sobrien 249160484Sobrienvoid 2492130561Sobriensymbol_clear_mri_common (symbolS *s) 249360484Sobrien{ 249460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 249560484Sobrien return; 249660484Sobrien s->sy_mri_common = 0; 249760484Sobrien} 249860484Sobrien 249960484Sobrien/* Return whether a symbol is an MRI common symbol. */ 250060484Sobrien 250160484Sobrienint 2502130561Sobriensymbol_mri_common_p (symbolS *s) 250360484Sobrien{ 250460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 250560484Sobrien return 0; 250660484Sobrien return s->sy_mri_common; 250760484Sobrien} 250860484Sobrien 250960484Sobrien/* Mark a symbol as having been written. */ 251060484Sobrien 251160484Sobrienvoid 2512130561Sobriensymbol_mark_written (symbolS *s) 251360484Sobrien{ 251460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 251560484Sobrien return; 251660484Sobrien s->written = 1; 251760484Sobrien} 251860484Sobrien 251960484Sobrien/* Clear the mark of whether a symbol has been written. */ 252060484Sobrien 252160484Sobrienvoid 2522130561Sobriensymbol_clear_written (symbolS *s) 252360484Sobrien{ 252460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 252560484Sobrien return; 252660484Sobrien s->written = 0; 252760484Sobrien} 252860484Sobrien 252960484Sobrien/* Return whether a symbol has been written. */ 253060484Sobrien 253160484Sobrienint 2532130561Sobriensymbol_written_p (symbolS *s) 253360484Sobrien{ 253460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 253560484Sobrien return 0; 253660484Sobrien return s->written; 253760484Sobrien} 253860484Sobrien 253960484Sobrien/* Mark a symbol has having been resolved. */ 254060484Sobrien 254160484Sobrienvoid 2542130561Sobriensymbol_mark_resolved (symbolS *s) 254360484Sobrien{ 254460484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 254560484Sobrien { 254660484Sobrien local_symbol_mark_resolved ((struct local_symbol *) s); 254760484Sobrien return; 254860484Sobrien } 254960484Sobrien s->sy_resolved = 1; 255060484Sobrien} 255160484Sobrien 255260484Sobrien/* Return whether a symbol has been resolved. */ 255360484Sobrien 255460484Sobrienint 2555130561Sobriensymbol_resolved_p (symbolS *s) 255660484Sobrien{ 255760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 255860484Sobrien return local_symbol_resolved_p ((struct local_symbol *) s); 255960484Sobrien return s->sy_resolved; 256060484Sobrien} 256160484Sobrien 256260484Sobrien/* Return whether a symbol is a section symbol. */ 256360484Sobrien 256460484Sobrienint 2565130561Sobriensymbol_section_p (symbolS *s ATTRIBUTE_UNUSED) 256660484Sobrien{ 256760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 256860484Sobrien return 0; 256960484Sobrien return (s->bsym->flags & BSF_SECTION_SYM) != 0; 257060484Sobrien} 257160484Sobrien 257260484Sobrien/* Return whether a symbol is equated to another symbol. */ 257360484Sobrien 257460484Sobrienint 2575130561Sobriensymbol_equated_p (symbolS *s) 257660484Sobrien{ 257760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 257860484Sobrien return 0; 257960484Sobrien return s->sy_value.X_op == O_symbol; 258060484Sobrien} 258160484Sobrien 258289857Sobrien/* Return whether a symbol is equated to another symbol, and should be 258389857Sobrien treated specially when writing out relocs. */ 258489857Sobrien 258589857Sobrienint 2586130561Sobriensymbol_equated_reloc_p (symbolS *s) 258789857Sobrien{ 258889857Sobrien if (LOCAL_SYMBOL_CHECK (s)) 258989857Sobrien return 0; 259089857Sobrien /* X_op_symbol, normally not used for O_symbol, is set by 259189857Sobrien resolve_symbol_value to flag expression syms that have been 259289857Sobrien equated. */ 259389857Sobrien return (s->sy_value.X_op == O_symbol 2594218822Sdim#if defined (OBJ_COFF) && defined (TE_PE) 2595218822Sdim && ! S_IS_WEAK (s) 2596218822Sdim#endif 259789857Sobrien && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL) 259889857Sobrien || ! S_IS_DEFINED (s) 259989857Sobrien || S_IS_COMMON (s))); 260089857Sobrien} 260189857Sobrien 260260484Sobrien/* Return whether a symbol has a constant value. */ 260360484Sobrien 260460484Sobrienint 2605130561Sobriensymbol_constant_p (symbolS *s) 260660484Sobrien{ 260760484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 260860484Sobrien return 1; 260960484Sobrien return s->sy_value.X_op == O_constant; 261060484Sobrien} 261160484Sobrien 2612218822Sdim/* Return whether a symbol was cloned and thus removed from the global 2613218822Sdim symbol list. */ 261460484Sobrien 2615218822Sdimint 2616218822Sdimsymbol_shadow_p (symbolS *s) 2617218822Sdim{ 2618218822Sdim if (LOCAL_SYMBOL_CHECK (s)) 2619218822Sdim return 0; 2620218822Sdim return s->sy_next == s; 2621218822Sdim} 2622218822Sdim 262360484Sobrien/* Return the BFD symbol for a symbol. */ 262460484Sobrien 262560484Sobrienasymbol * 2626130561Sobriensymbol_get_bfdsym (symbolS *s) 262760484Sobrien{ 262860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 262960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 263060484Sobrien return s->bsym; 263160484Sobrien} 263260484Sobrien 263360484Sobrien/* Set the BFD symbol for a symbol. */ 263460484Sobrien 263560484Sobrienvoid 2636130561Sobriensymbol_set_bfdsym (symbolS *s, asymbol *bsym) 263760484Sobrien{ 263860484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 263960484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 2640218822Sdim /* Usually, it is harmless to reset a symbol to a BFD section 2641218822Sdim symbol. For example, obj_elf_change_section sets the BFD symbol 2642218822Sdim of an old symbol with the newly created section symbol. But when 2643218822Sdim we have multiple sections with the same name, the newly created 2644218822Sdim section may have the same name as an old section. We check if the 2645218822Sdim old symbol has been already marked as a section symbol before 2646218822Sdim resetting it. */ 2647218822Sdim if ((s->bsym->flags & BSF_SECTION_SYM) == 0) 2648218822Sdim s->bsym = bsym; 2649218822Sdim /* else XXX - What do we do now ? */ 265060484Sobrien} 265160484Sobrien 265260484Sobrien#ifdef OBJ_SYMFIELD_TYPE 265360484Sobrien 265460484Sobrien/* Get a pointer to the object format information for a symbol. */ 265560484Sobrien 265660484SobrienOBJ_SYMFIELD_TYPE * 2657130561Sobriensymbol_get_obj (symbolS *s) 265860484Sobrien{ 265960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 266060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 266160484Sobrien return &s->sy_obj; 266260484Sobrien} 266360484Sobrien 266460484Sobrien/* Set the object format information for a symbol. */ 266560484Sobrien 266660484Sobrienvoid 2667130561Sobriensymbol_set_obj (symbolS *s, OBJ_SYMFIELD_TYPE *o) 266860484Sobrien{ 266960484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 267060484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 267160484Sobrien s->sy_obj = *o; 267260484Sobrien} 267360484Sobrien 267460484Sobrien#endif /* OBJ_SYMFIELD_TYPE */ 267560484Sobrien 267660484Sobrien#ifdef TC_SYMFIELD_TYPE 267760484Sobrien 267860484Sobrien/* Get a pointer to the processor information for a symbol. */ 267960484Sobrien 268060484SobrienTC_SYMFIELD_TYPE * 2681130561Sobriensymbol_get_tc (symbolS *s) 268260484Sobrien{ 268360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 268460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 268560484Sobrien return &s->sy_tc; 268660484Sobrien} 268760484Sobrien 268860484Sobrien/* Set the processor information for a symbol. */ 268960484Sobrien 269060484Sobrienvoid 2691130561Sobriensymbol_set_tc (symbolS *s, TC_SYMFIELD_TYPE *o) 269260484Sobrien{ 269360484Sobrien if (LOCAL_SYMBOL_CHECK (s)) 269460484Sobrien s = local_symbol_convert ((struct local_symbol *) s); 269560484Sobrien s->sy_tc = *o; 269660484Sobrien} 269760484Sobrien 269860484Sobrien#endif /* TC_SYMFIELD_TYPE */ 269960484Sobrien 270060484Sobrienvoid 2701130561Sobriensymbol_begin (void) 270233965Sjdp{ 270333965Sjdp symbol_lastP = NULL; 270477298Sobrien symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ 270533965Sjdp sy_hash = hash_new (); 270660484Sobrien local_hash = hash_new (); 270733965Sjdp 270833965Sjdp memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol)); 270933965Sjdp#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL) 271033965Sjdp abs_symbol.bsym = bfd_abs_section.symbol; 271133965Sjdp#endif 271233965Sjdp abs_symbol.sy_value.X_op = O_constant; 271333965Sjdp abs_symbol.sy_frag = &zero_address_frag; 271433965Sjdp 271533965Sjdp if (LOCAL_LABELS_FB) 271633965Sjdp fb_label_init (); 271733965Sjdp} 271833965Sjdp 271933965Sjdpint indent_level; 272033965Sjdp 272160484Sobrien/* Maximum indent level. 272260484Sobrien Available for modification inside a gdb session. */ 2723218822Sdimstatic int max_indent_level = 8; 272460484Sobrien 272533965Sjdpvoid 2726130561Sobrienprint_symbol_value_1 (FILE *file, symbolS *sym) 272733965Sjdp{ 272833965Sjdp const char *name = S_GET_NAME (sym); 272933965Sjdp if (!name || !name[0]) 273033965Sjdp name = "(unnamed)"; 273133965Sjdp fprintf (file, "sym %lx %s", (unsigned long) sym, name); 273260484Sobrien 273360484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 273460484Sobrien { 273560484Sobrien struct local_symbol *locsym = (struct local_symbol *) sym; 273660484Sobrien if (local_symbol_get_frag (locsym) != &zero_address_frag 273760484Sobrien && local_symbol_get_frag (locsym) != NULL) 273860484Sobrien fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym)); 273960484Sobrien if (local_symbol_resolved_p (locsym)) 274060484Sobrien fprintf (file, " resolved"); 274160484Sobrien fprintf (file, " local"); 274260484Sobrien } 274360484Sobrien else 274460484Sobrien { 274560484Sobrien if (sym->sy_frag != &zero_address_frag) 274660484Sobrien fprintf (file, " frag %lx", (long) sym->sy_frag); 274760484Sobrien if (sym->written) 274860484Sobrien fprintf (file, " written"); 274960484Sobrien if (sym->sy_resolved) 275060484Sobrien fprintf (file, " resolved"); 275160484Sobrien else if (sym->sy_resolving) 275260484Sobrien fprintf (file, " resolving"); 275360484Sobrien if (sym->sy_used_in_reloc) 275460484Sobrien fprintf (file, " used-in-reloc"); 275560484Sobrien if (sym->sy_used) 275660484Sobrien fprintf (file, " used"); 275760484Sobrien if (S_IS_LOCAL (sym)) 275860484Sobrien fprintf (file, " local"); 2759218822Sdim if (S_IS_EXTERNAL (sym)) 276060484Sobrien fprintf (file, " extern"); 2761218822Sdim if (S_IS_WEAK (sym)) 2762218822Sdim fprintf (file, " weak"); 276360484Sobrien if (S_IS_DEBUG (sym)) 276460484Sobrien fprintf (file, " debug"); 276560484Sobrien if (S_IS_DEFINED (sym)) 276660484Sobrien fprintf (file, " defined"); 276760484Sobrien } 2768218822Sdim if (S_IS_WEAKREFR (sym)) 2769218822Sdim fprintf (file, " weakrefr"); 2770218822Sdim if (S_IS_WEAKREFD (sym)) 2771218822Sdim fprintf (file, " weakrefd"); 277233965Sjdp fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym))); 277360484Sobrien if (symbol_resolved_p (sym)) 277433965Sjdp { 277533965Sjdp segT s = S_GET_SEGMENT (sym); 277633965Sjdp 277733965Sjdp if (s != undefined_section 2778104834Sobrien && s != expr_section) 277933965Sjdp fprintf (file, " %lx", (long) S_GET_VALUE (sym)); 278033965Sjdp } 278160484Sobrien else if (indent_level < max_indent_level 278260484Sobrien && S_GET_SEGMENT (sym) != undefined_section) 278333965Sjdp { 278433965Sjdp indent_level++; 278533965Sjdp fprintf (file, "\n%*s<", indent_level * 4, ""); 278660484Sobrien if (LOCAL_SYMBOL_CHECK (sym)) 278760484Sobrien fprintf (file, "constant %lx", 278889857Sobrien (long) ((struct local_symbol *) sym)->lsy_value); 278960484Sobrien else 279060484Sobrien print_expr_1 (file, &sym->sy_value); 279133965Sjdp fprintf (file, ">"); 279233965Sjdp indent_level--; 279333965Sjdp } 279433965Sjdp fflush (file); 279533965Sjdp} 279633965Sjdp 279733965Sjdpvoid 2798130561Sobrienprint_symbol_value (symbolS *sym) 279933965Sjdp{ 280033965Sjdp indent_level = 0; 280133965Sjdp print_symbol_value_1 (stderr, sym); 280233965Sjdp fprintf (stderr, "\n"); 280333965Sjdp} 280433965Sjdp 280560484Sobrienstatic void 2806130561Sobrienprint_binary (FILE *file, const char *name, expressionS *exp) 280760484Sobrien{ 280860484Sobrien indent_level++; 280960484Sobrien fprintf (file, "%s\n%*s<", name, indent_level * 4, ""); 281060484Sobrien print_symbol_value_1 (file, exp->X_add_symbol); 281160484Sobrien fprintf (file, ">\n%*s<", indent_level * 4, ""); 281260484Sobrien print_symbol_value_1 (file, exp->X_op_symbol); 281360484Sobrien fprintf (file, ">"); 281460484Sobrien indent_level--; 281560484Sobrien} 281660484Sobrien 281733965Sjdpvoid 2818130561Sobrienprint_expr_1 (FILE *file, expressionS *exp) 281933965Sjdp{ 282033965Sjdp fprintf (file, "expr %lx ", (long) exp); 282133965Sjdp switch (exp->X_op) 282233965Sjdp { 282333965Sjdp case O_illegal: 282433965Sjdp fprintf (file, "illegal"); 282533965Sjdp break; 282633965Sjdp case O_absent: 282733965Sjdp fprintf (file, "absent"); 282833965Sjdp break; 282933965Sjdp case O_constant: 283033965Sjdp fprintf (file, "constant %lx", (long) exp->X_add_number); 283133965Sjdp break; 283233965Sjdp case O_symbol: 283333965Sjdp indent_level++; 283433965Sjdp fprintf (file, "symbol\n%*s<", indent_level * 4, ""); 283533965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 283633965Sjdp fprintf (file, ">"); 283733965Sjdp maybe_print_addnum: 283833965Sjdp if (exp->X_add_number) 283933965Sjdp fprintf (file, "\n%*s%lx", indent_level * 4, "", 284033965Sjdp (long) exp->X_add_number); 284133965Sjdp indent_level--; 284233965Sjdp break; 284333965Sjdp case O_register: 284433965Sjdp fprintf (file, "register #%d", (int) exp->X_add_number); 284533965Sjdp break; 284633965Sjdp case O_big: 284733965Sjdp fprintf (file, "big"); 284833965Sjdp break; 284933965Sjdp case O_uminus: 285033965Sjdp fprintf (file, "uminus -<"); 285133965Sjdp indent_level++; 285233965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 285333965Sjdp fprintf (file, ">"); 285433965Sjdp goto maybe_print_addnum; 285533965Sjdp case O_bit_not: 285633965Sjdp fprintf (file, "bit_not"); 285733965Sjdp break; 285833965Sjdp case O_multiply: 285960484Sobrien print_binary (file, "multiply", exp); 286033965Sjdp break; 286133965Sjdp case O_divide: 286260484Sobrien print_binary (file, "divide", exp); 286333965Sjdp break; 286433965Sjdp case O_modulus: 286560484Sobrien print_binary (file, "modulus", exp); 286633965Sjdp break; 286733965Sjdp case O_left_shift: 286860484Sobrien print_binary (file, "lshift", exp); 286933965Sjdp break; 287033965Sjdp case O_right_shift: 287160484Sobrien print_binary (file, "rshift", exp); 287233965Sjdp break; 287333965Sjdp case O_bit_inclusive_or: 287460484Sobrien print_binary (file, "bit_ior", exp); 287533965Sjdp break; 287633965Sjdp case O_bit_exclusive_or: 287760484Sobrien print_binary (file, "bit_xor", exp); 287833965Sjdp break; 287933965Sjdp case O_bit_and: 288060484Sobrien print_binary (file, "bit_and", exp); 288133965Sjdp break; 288233965Sjdp case O_eq: 288360484Sobrien print_binary (file, "eq", exp); 288433965Sjdp break; 288533965Sjdp case O_ne: 288660484Sobrien print_binary (file, "ne", exp); 288733965Sjdp break; 288833965Sjdp case O_lt: 288960484Sobrien print_binary (file, "lt", exp); 289033965Sjdp break; 289133965Sjdp case O_le: 289260484Sobrien print_binary (file, "le", exp); 289333965Sjdp break; 289433965Sjdp case O_ge: 289560484Sobrien print_binary (file, "ge", exp); 289633965Sjdp break; 289733965Sjdp case O_gt: 289860484Sobrien print_binary (file, "gt", exp); 289933965Sjdp break; 290033965Sjdp case O_logical_and: 290160484Sobrien print_binary (file, "logical_and", exp); 290233965Sjdp break; 290333965Sjdp case O_logical_or: 290460484Sobrien print_binary (file, "logical_or", exp); 290533965Sjdp break; 290633965Sjdp case O_add: 290733965Sjdp indent_level++; 290833965Sjdp fprintf (file, "add\n%*s<", indent_level * 4, ""); 290933965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 291033965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 291133965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 291233965Sjdp fprintf (file, ">"); 291333965Sjdp goto maybe_print_addnum; 291433965Sjdp case O_subtract: 291533965Sjdp indent_level++; 291633965Sjdp fprintf (file, "subtract\n%*s<", indent_level * 4, ""); 291733965Sjdp print_symbol_value_1 (file, exp->X_add_symbol); 291833965Sjdp fprintf (file, ">\n%*s<", indent_level * 4, ""); 291933965Sjdp print_symbol_value_1 (file, exp->X_op_symbol); 292033965Sjdp fprintf (file, ">"); 292133965Sjdp goto maybe_print_addnum; 292233965Sjdp default: 292333965Sjdp fprintf (file, "{unknown opcode %d}", (int) exp->X_op); 292433965Sjdp break; 292533965Sjdp } 292633965Sjdp fflush (stdout); 292733965Sjdp} 292833965Sjdp 292933965Sjdpvoid 2930130561Sobrienprint_expr (expressionS *exp) 293133965Sjdp{ 293233965Sjdp print_expr_1 (stderr, exp); 293333965Sjdp fprintf (stderr, "\n"); 293433965Sjdp} 293533965Sjdp 293633965Sjdpvoid 2937130561Sobriensymbol_print_statistics (FILE *file) 293833965Sjdp{ 293933965Sjdp hash_print_statistics (file, "symbol table", sy_hash); 294060484Sobrien hash_print_statistics (file, "mini local symbol table", local_hash); 294160484Sobrien fprintf (file, "%lu mini local symbols created, %lu converted\n", 294260484Sobrien local_symbol_count, local_symbol_conversion_count); 2943218822Sdim} 2944218822Sdim 2945218822Sdim#ifdef OBJ_COMPLEX_RELC 2946218822Sdim 2947218822Sdim/* Convert given symbol to a new complex-relocation symbol name. This 2948218822Sdim may be a recursive function, since it might be called for non-leaf 2949218822Sdim nodes (plain symbols) in the expression tree. The caller owns the 2950218822Sdim returning string, so should free it eventually. Errors are 2951218822Sdim indicated via as_bad and a NULL return value. The given symbol 2952218822Sdim is marked with sy_used_in_reloc. */ 2953218822Sdim 2954218822Sdimchar * 2955218822Sdimsymbol_relc_make_sym (symbolS * sym) 2956218822Sdim{ 2957218822Sdim char * terminal = NULL; 2958218822Sdim const char * sname; 2959218822Sdim char typetag; 2960218822Sdim int sname_len; 2961218822Sdim 2962218822Sdim assert (sym != NULL); 2963218822Sdim 2964218822Sdim /* Recurse to symbol_relc_make_expr if this symbol 2965218822Sdim is defined as an expression or a plain value. */ 2966218822Sdim if ( S_GET_SEGMENT (sym) == expr_section 2967218822Sdim || S_GET_SEGMENT (sym) == absolute_section) 2968218822Sdim return symbol_relc_make_expr (& sym->sy_value); 2969218822Sdim 2970218822Sdim /* This may be a "fake symbol" L0\001, referring to ".". 2971218822Sdim Write out a special null symbol to refer to this position. */ 2972218822Sdim if (! strcmp (S_GET_NAME (sym), FAKE_LABEL_NAME)) 2973218822Sdim return xstrdup ("."); 2974218822Sdim 2975218822Sdim /* We hope this is a plain leaf symbol. Construct the encoding 2976218822Sdim as {S,s}II...:CCCCCCC.... 2977218822Sdim where 'S'/'s' means section symbol / plain symbol 2978218822Sdim III is decimal for the symbol name length 2979218822Sdim CCC is the symbol name itself. */ 2980218822Sdim symbol_mark_used_in_reloc (sym); 2981218822Sdim 2982218822Sdim sname = S_GET_NAME (sym); 2983218822Sdim sname_len = strlen (sname); 2984218822Sdim typetag = symbol_section_p (sym) ? 'S' : 's'; 2985218822Sdim 2986218822Sdim terminal = xmalloc (1 /* S or s */ 2987218822Sdim + 8 /* sname_len in decimal */ 2988218822Sdim + 1 /* _ spacer */ 2989218822Sdim + sname_len /* name itself */ 2990218822Sdim + 1 /* \0 */ ); 2991218822Sdim 2992218822Sdim sprintf (terminal, "%c%d:%s", typetag, sname_len, sname); 2993218822Sdim return terminal; 2994218822Sdim} 2995218822Sdim 2996218822Sdim/* Convert given value to a new complex-relocation symbol name. This 2997218822Sdim is a non-recursive function, since it is be called for leaf nodes 2998218822Sdim (plain values) in the expression tree. The caller owns the 2999218822Sdim returning string, so should free() it eventually. No errors. */ 3000218822Sdim 3001218822Sdimchar * 3002218822Sdimsymbol_relc_make_value (offsetT val) 3003218822Sdim{ 3004218822Sdim char * terminal = xmalloc (28); /* Enough for long long. */ 3005218822Sdim 3006218822Sdim terminal[0] = '#'; 3007218822Sdim sprintf_vma (& terminal[1], val); 3008218822Sdim return terminal; 3009218822Sdim} 3010218822Sdim 3011218822Sdim/* Convert given expression to a new complex-relocation symbol name. 3012218822Sdim This is a recursive function, since it traverses the entire given 3013218822Sdim expression tree. The caller owns the returning string, so should 3014218822Sdim free() it eventually. Errors are indicated via as_bad() and a NULL 3015218822Sdim return value. */ 3016218822Sdim 3017218822Sdimchar * 3018218822Sdimsymbol_relc_make_expr (expressionS * exp) 3019218822Sdim{ 3020218822Sdim char * opstr = NULL; /* Operator prefix string. */ 3021218822Sdim int arity = 0; /* Arity of this operator. */ 3022218822Sdim char * operands[3]; /* Up to three operands. */ 3023218822Sdim char * concat_string = NULL; 3024218822Sdim 3025218822Sdim operands[0] = operands[1] = operands[2] = NULL; 3026218822Sdim 3027218822Sdim assert (exp != NULL); 3028218822Sdim 3029218822Sdim /* Match known operators -> fill in opstr, arity, operands[] and fall 3030218822Sdim through to construct subexpression fragments; may instead return 3031218822Sdim string directly for leaf nodes. */ 3032218822Sdim 3033218822Sdim /* See expr.h for the meaning of all these enums. Many operators 3034218822Sdim have an unnatural arity (X_add_number implicitly added). The 3035218822Sdim conversion logic expands them to explicit "+" subexpressions. */ 3036218822Sdim 3037218822Sdim switch (exp->X_op) 3038218822Sdim { 3039218822Sdim default: 3040218822Sdim as_bad ("Unknown expression operator (enum %d)", exp->X_op); 3041218822Sdim break; 3042218822Sdim 3043218822Sdim /* Leaf nodes. */ 3044218822Sdim case O_constant: 3045218822Sdim return symbol_relc_make_value (exp->X_add_number); 3046218822Sdim 3047218822Sdim case O_symbol: 3048218822Sdim if (exp->X_add_number) 3049218822Sdim { 3050218822Sdim arity = 2; 3051218822Sdim opstr = "+"; 3052218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); 3053218822Sdim operands[1] = symbol_relc_make_value (exp->X_add_number); 3054218822Sdim break; 3055218822Sdim } 3056218822Sdim else 3057218822Sdim return symbol_relc_make_sym (exp->X_add_symbol); 3058218822Sdim 3059218822Sdim /* Helper macros for nesting nodes. */ 3060218822Sdim 3061218822Sdim#define HANDLE_XADD_OPT1(str_) \ 3062218822Sdim if (exp->X_add_number) \ 3063218822Sdim { \ 3064218822Sdim arity = 2; \ 3065218822Sdim opstr = "+:" str_; \ 3066218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3067218822Sdim operands[1] = symbol_relc_make_value (exp->X_add_number); \ 3068218822Sdim break; \ 3069218822Sdim } \ 3070218822Sdim else \ 3071218822Sdim { \ 3072218822Sdim arity = 1; \ 3073218822Sdim opstr = str_; \ 3074218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3075218822Sdim } \ 3076218822Sdim break 3077218822Sdim 3078218822Sdim#define HANDLE_XADD_OPT2(str_) \ 3079218822Sdim if (exp->X_add_number) \ 3080218822Sdim { \ 3081218822Sdim arity = 3; \ 3082218822Sdim opstr = "+:" str_; \ 3083218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3084218822Sdim operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \ 3085218822Sdim operands[2] = symbol_relc_make_value (exp->X_add_number); \ 3086218822Sdim } \ 3087218822Sdim else \ 3088218822Sdim { \ 3089218822Sdim arity = 2; \ 3090218822Sdim opstr = str_; \ 3091218822Sdim operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \ 3092218822Sdim operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \ 3093218822Sdim } \ 3094218822Sdim break 3095218822Sdim 3096218822Sdim /* Nesting nodes. */ 3097218822Sdim 3098218822Sdim case O_uminus: HANDLE_XADD_OPT1 ("0-"); 3099218822Sdim case O_bit_not: HANDLE_XADD_OPT1 ("~"); 3100218822Sdim case O_logical_not: HANDLE_XADD_OPT1 ("!"); 3101218822Sdim case O_multiply: HANDLE_XADD_OPT2 ("*"); 3102218822Sdim case O_divide: HANDLE_XADD_OPT2 ("/"); 3103218822Sdim case O_modulus: HANDLE_XADD_OPT2 ("%"); 3104218822Sdim case O_left_shift: HANDLE_XADD_OPT2 ("<<"); 3105218822Sdim case O_right_shift: HANDLE_XADD_OPT2 (">>"); 3106218822Sdim case O_bit_inclusive_or: HANDLE_XADD_OPT2 ("|"); 3107218822Sdim case O_bit_exclusive_or: HANDLE_XADD_OPT2 ("^"); 3108218822Sdim case O_bit_and: HANDLE_XADD_OPT2 ("&"); 3109218822Sdim case O_add: HANDLE_XADD_OPT2 ("+"); 3110218822Sdim case O_subtract: HANDLE_XADD_OPT2 ("-"); 3111218822Sdim case O_eq: HANDLE_XADD_OPT2 ("=="); 3112218822Sdim case O_ne: HANDLE_XADD_OPT2 ("!="); 3113218822Sdim case O_lt: HANDLE_XADD_OPT2 ("<"); 3114218822Sdim case O_le: HANDLE_XADD_OPT2 ("<="); 3115218822Sdim case O_ge: HANDLE_XADD_OPT2 (">="); 3116218822Sdim case O_gt: HANDLE_XADD_OPT2 (">"); 3117218822Sdim case O_logical_and: HANDLE_XADD_OPT2 ("&&"); 3118218822Sdim case O_logical_or: HANDLE_XADD_OPT2 ("||"); 3119218822Sdim } 3120218822Sdim 3121218822Sdim /* Validate & reject early. */ 3122218822Sdim if (arity >= 1 && ((operands[0] == NULL) || (strlen (operands[0]) == 0))) 3123218822Sdim opstr = NULL; 3124218822Sdim if (arity >= 2 && ((operands[1] == NULL) || (strlen (operands[1]) == 0))) 3125218822Sdim opstr = NULL; 3126218822Sdim if (arity >= 3 && ((operands[2] == NULL) || (strlen (operands[2]) == 0))) 3127218822Sdim opstr = NULL; 3128218822Sdim 3129218822Sdim if (opstr == NULL) 3130218822Sdim concat_string = NULL; 3131218822Sdim else 3132218822Sdim { 3133218822Sdim /* Allocate new string; include inter-operand padding gaps etc. */ 3134218822Sdim concat_string = xmalloc (strlen (opstr) 3135218822Sdim + 1 3136218822Sdim + (arity >= 1 ? (strlen (operands[0]) + 1 ) : 0) 3137218822Sdim + (arity >= 2 ? (strlen (operands[1]) + 1 ) : 0) 3138218822Sdim + (arity >= 3 ? (strlen (operands[2]) + 0 ) : 0) 3139218822Sdim + 1); 3140218822Sdim assert (concat_string != NULL); 3141218822Sdim 3142218822Sdim /* Format the thing. */ 3143218822Sdim sprintf (concat_string, 3144218822Sdim (arity == 0 ? "%s" : 3145218822Sdim arity == 1 ? "%s:%s" : 3146218822Sdim arity == 2 ? "%s:%s:%s" : 3147218822Sdim /* arity == 3 */ "%s:%s:%s:%s"), 3148218822Sdim opstr, operands[0], operands[1], operands[2]); 3149218822Sdim } 3150218822Sdim 3151218822Sdim /* Free operand strings (not opstr). */ 3152218822Sdim if (arity >= 1) xfree (operands[0]); 3153218822Sdim if (arity >= 2) xfree (operands[1]); 3154218822Sdim if (arity >= 3) xfree (operands[2]); 3155218822Sdim 3156218822Sdim return concat_string; 3157218822Sdim} 3158218822Sdim 315960484Sobrien#endif 3160