X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fsymbols.c;h=79cdb82ba8c09f81f2493d99da1932b1b51c1101;hb=54a01e885b23df89e7e1e1585e896e0b7c53cf1d;hp=19b3dbc667eb50cf5ad9442eaffe46667d94da5d;hpb=2469b3c58447e98e073ffe7ab6c9627dbbd1aa81;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/symbols.c b/gas/symbols.c index 19b3dbc667..79cdb82ba8 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -1,5 +1,5 @@ /* symbols.c -symbol table- - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -24,9 +24,142 @@ #include "safe-ctype.h" #include "obstack.h" /* For "symbols.h" */ #include "subsegs.h" -#include "struc-symbol.h" #include "write.h" +struct symbol_flags +{ + /* Whether the symbol is a local_symbol. */ + unsigned int sy_local_symbol : 1; + + /* Weather symbol has been written. */ + unsigned int sy_written : 1; + + /* Whether symbol value has been completely resolved (used during + final pass over symbol table). */ + unsigned int sy_resolved : 1; + + /* Whether the symbol value is currently being resolved (used to + detect loops in symbol dependencies). */ + unsigned int sy_resolving : 1; + + /* Whether the symbol value is used in a reloc. This is used to + ensure that symbols used in relocs are written out, even if they + are local and would otherwise not be. */ + unsigned int sy_used_in_reloc : 1; + + /* Whether the symbol is used as an operand or in an expression. + NOTE: Not all the backends keep this information accurate; + backends which use this bit are responsible for setting it when + a symbol is used in backend routines. */ + unsigned int sy_used : 1; + + /* Whether the symbol can be re-defined. */ + unsigned int sy_volatile : 1; + + /* Whether the symbol is a forward reference. */ + unsigned int sy_forward_ref : 1; + + /* This is set if the symbol is defined in an MRI common section. + We handle such sections as single common symbols, so symbols + defined within them must be treated specially by the relocation + routines. */ + unsigned int sy_mri_common : 1; + + /* This is set if the symbol is set with a .weakref directive. */ + unsigned int sy_weakrefr : 1; + + /* This is set when the symbol is referenced as part of a .weakref + directive, but only if the symbol was not in the symbol table + before. It is cleared as soon as any direct reference to the + symbol is present. */ + unsigned int sy_weakrefd : 1; +}; + +/* The information we keep for a symbol. Note that the symbol table + holds pointers both to this and to local_symbol structures. See + below. */ + +struct symbol +{ + /* Symbol flags. */ + struct symbol_flags sy_flags; + + /* BFD symbol */ + asymbol *bsym; + + /* The value of the symbol. */ + expressionS sy_value; + + /* Forwards and (optionally) backwards chain pointers. */ + struct symbol *sy_next; + struct symbol *sy_previous; + + /* Pointer to the frag this symbol is attached to, if any. + Otherwise, NULL. */ + struct frag *sy_frag; + +#ifdef OBJ_SYMFIELD_TYPE + OBJ_SYMFIELD_TYPE sy_obj; +#endif + +#ifdef TC_SYMFIELD_TYPE + TC_SYMFIELD_TYPE sy_tc; +#endif + +#ifdef TARGET_SYMBOL_FIELDS + TARGET_SYMBOL_FIELDS +#endif +}; + +/* A pointer in the symbol may point to either a complete symbol + (struct symbol above) or to a local symbol (struct local_symbol + defined here). The symbol code can detect the case by examining + the first field. It is always NULL for a local symbol. + + We do this because we ordinarily only need a small amount of + information for a local symbol. The symbol table takes up a lot of + space, and storing less information for a local symbol can make a + big difference in assembler memory usage when assembling a large + file. */ + +struct local_symbol +{ + /* Symbol flags. Only sy_local_symbol and sy_resolved are relevant. */ + struct symbol_flags lsy_flags; + + /* The symbol section. This also serves as a flag. If this is + reg_section, then this symbol has been converted into a regular + symbol, and lsy_sym points to it. */ + segT lsy_section; + + /* The symbol name. */ + const char *lsy_name; + + /* The symbol frag or the real symbol, depending upon the value in + lsy_section. */ + union + { + fragS *lsy_frag; + symbolS *lsy_sym; + } u; + + /* The value of the symbol. */ + valueT lsy_value; + +#ifdef TC_LOCAL_SYMFIELD_TYPE + TC_LOCAL_SYMFIELD_TYPE lsy_tc; +#endif +}; + +#define local_symbol_converted_p(l) ((l)->lsy_section == reg_section) +#define local_symbol_mark_converted(l) ((l)->lsy_section = reg_section) +#define local_symbol_resolved_p(l) ((l)->lsy_flags.sy_resolved) +#define local_symbol_mark_resolved(l) ((l)->lsy_flags.sy_resolved = 1) +#define local_symbol_get_frag(l) ((l)->u.lsy_frag) +#define local_symbol_set_frag(l, f) ((l)->u.lsy_frag = (f)) +#define local_symbol_get_real_symbol(l) ((l)->u.lsy_sym) +#define local_symbol_set_real_symbol(l, s) ((l)->u.lsy_sym = (s)) + /* This is non-zero if symbols are case sensitive, which is the default. */ int symbols_case_sensitive = 1; @@ -108,6 +241,7 @@ save_symbol_name (const char *name) size_t name_length; char *ret; + gas_assert (name != NULL); name_length = strlen (name) + 1; /* +1 for \0. */ obstack_grow (¬es, name, name_length); ret = (char *) obstack_finish (¬es); @@ -407,8 +541,7 @@ colon (/* Just seen "x:" - rattle symbols & frags. */ } else { -#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \ - && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT)) +#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT)) static const char *od_buf = ""; #else char od_buf[100]; @@ -619,9 +752,22 @@ symbol_clone (symbolS *orgsymP, int replace) return newsymP; } +/* If S is a local symbol that has been converted, return the + converted symbol. Otherwise return S. */ + +static inline symbolS * +get_real_sym (symbolS *s) +{ + if (s != NULL + && s->sy_flags.sy_local_symbol + && local_symbol_converted_p ((struct local_symbol *) s)) + s = local_symbol_get_real_symbol ((struct local_symbol *) s); + return s; +} + /* Referenced symbols, if they are forward references, need to be cloned (without replacing the original) so that the value of the referenced - symbols at the point of use . */ + symbols at the point of use is saved by the clone. */ #undef symbol_clone_if_forward_ref symbolS * @@ -629,8 +775,10 @@ symbol_clone_if_forward_ref (symbolS *symbolP, int is_forward) { if (symbolP && !LOCAL_SYMBOL_CHECK (symbolP)) { - symbolS *add_symbol = symbolP->sy_value.X_add_symbol; - symbolS *op_symbol = symbolP->sy_value.X_op_symbol; + symbolS *orig_add_symbol = get_real_sym (symbolP->sy_value.X_add_symbol); + symbolS *orig_op_symbol = get_real_sym (symbolP->sy_value.X_op_symbol); + symbolS *add_symbol = orig_add_symbol; + symbolS *op_symbol = orig_op_symbol; if (symbolP->sy_flags.sy_forward_ref) is_forward = 1; @@ -659,8 +807,8 @@ symbol_clone_if_forward_ref (symbolS *symbolP, int is_forward) } if (symbolP->sy_flags.sy_forward_ref - || add_symbol != symbolP->sy_value.X_add_symbol - || op_symbol != symbolP->sy_value.X_op_symbol) + || add_symbol != orig_add_symbol + || op_symbol != orig_op_symbol) { if (symbolP != &dot_symbol) { @@ -695,6 +843,12 @@ symbol_temp_new_now (void) return symbol_temp_new (now_seg, frag_now_fix (), frag_now); } +symbolS * +symbol_temp_new_now_octets (void) +{ + return symbol_temp_new (now_seg, frag_now_fix_octets (), frag_now); +} + symbolS * symbol_temp_make (void) { @@ -913,6 +1067,20 @@ verify_symbol_chain (symbolS *rootP, symbolS *lastP) gas_assert (lastP == symbolP); } +int +symbol_on_chain (symbolS *s, symbolS *rootPP, symbolS *lastPP) +{ + return (!LOCAL_SYMBOL_CHECK (s) + && ((s->sy_next != s + && s->sy_next != NULL + && s->sy_next->sy_previous == s) + || s == lastPP) + && ((s->sy_previous != s + && s->sy_previous != NULL + && s->sy_previous->sy_next == s) + || s == rootPP)); +} + #ifdef OBJ_COMPLEX_RELC static int @@ -923,19 +1091,6 @@ use_complex_relocs_for (symbolS * symp) case O_constant: return 0; - case O_symbol: - case O_symbol_rva: - case O_uminus: - case O_bit_not: - case O_logical_not: - if ( (S_IS_COMMON (symp->sy_value.X_add_symbol) - || S_IS_LOCAL (symp->sy_value.X_add_symbol)) - && - (S_IS_DEFINED (symp->sy_value.X_add_symbol) - && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section)) - return 0; - break; - case O_multiply: case O_divide: case O_modulus: @@ -955,18 +1110,22 @@ use_complex_relocs_for (symbolS * symp) case O_gt: case O_logical_and: case O_logical_or: - - if ( (S_IS_COMMON (symp->sy_value.X_add_symbol) - || S_IS_LOCAL (symp->sy_value.X_add_symbol)) - && - (S_IS_COMMON (symp->sy_value.X_op_symbol) + if ((S_IS_COMMON (symp->sy_value.X_op_symbol) || S_IS_LOCAL (symp->sy_value.X_op_symbol)) - - && S_IS_DEFINED (symp->sy_value.X_add_symbol) && S_IS_DEFINED (symp->sy_value.X_op_symbol) - && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section && S_GET_SEGMENT (symp->sy_value.X_op_symbol) != expr_section) - return 0; + { + case O_symbol: + case O_symbol_rva: + case O_uminus: + case O_bit_not: + case O_logical_not: + if ((S_IS_COMMON (symp->sy_value.X_add_symbol) + || S_IS_LOCAL (symp->sy_value.X_add_symbol)) + && S_IS_DEFINED (symp->sy_value.X_add_symbol) + && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section) + return 0; + } break; default: @@ -1047,7 +1206,7 @@ valueT resolve_symbol_value (symbolS *symp) { int resolved; - valueT final_val = 0; + valueT final_val; segT final_seg; if (LOCAL_SYMBOL_CHECK (symp)) @@ -1058,7 +1217,13 @@ resolve_symbol_value (symbolS *symp) if (local_symbol_resolved_p (locsym)) return final_val; - final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE; + /* Symbols whose section has SEC_ELF_OCTETS set, + resolve to octets instead of target bytes. */ + if (locsym->lsy_section->flags & SEC_OCTETS) + final_val += local_symbol_get_frag (locsym)->fr_address; + else + final_val += (local_symbol_get_frag (locsym)->fr_address + / OCTETS_PER_BYTE); if (finalize_syms) { @@ -1071,10 +1236,18 @@ resolve_symbol_value (symbolS *symp) if (symp->sy_flags.sy_resolved) { + final_val = 0; + while (symp->sy_value.X_op == O_symbol + && symp->sy_value.X_add_symbol->sy_flags.sy_resolved) + { + final_val += symp->sy_value.X_add_number; + symp = symp->sy_value.X_add_symbol; + } if (symp->sy_value.X_op == O_constant) - return (valueT) symp->sy_value.X_add_number; + final_val += symp->sy_value.X_add_number; else - return 0; + final_val = 0; + return final_val; } resolved = 0; @@ -1131,6 +1304,7 @@ resolve_symbol_value (symbolS *symp) resolved = 1; } + final_val = 0; final_seg = undefined_section; goto exit_dont_set_value; } @@ -1162,7 +1336,12 @@ resolve_symbol_value (symbolS *symp) /* Fall through. */ case O_constant: - final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; + /* Symbols whose section has SEC_ELF_OCTETS set, + resolve to octets instead of target bytes. */ + if (symp->bsym->section->flags & SEC_OCTETS) + final_val += symp->sy_frag->fr_address; + else + final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; if (final_seg == expr_section) final_seg = absolute_section; /* Fall through. */ @@ -1215,11 +1394,16 @@ resolve_symbol_value (symbolS *symp) relocation to detect this case, and convert the relocation to be against the symbol to which this symbol is equated. */ - if (! S_IS_DEFINED (add_symbol) + if (seg_left == undefined_section + || bfd_is_com_section (seg_left) #if defined (OBJ_COFF) && defined (TE_PE) || S_IS_WEAK (add_symbol) #endif - || S_IS_COMMON (add_symbol)) + || (finalize_syms + && ((final_seg == expr_section + && seg_left != expr_section + && seg_left != absolute_section) + || symbol_shadow_p (symp)))) { if (finalize_syms) { @@ -1230,25 +1414,6 @@ resolve_symbol_value (symbolS *symp) symp->sy_value.X_op_symbol = add_symbol; } final_seg = seg_left; - final_val = 0; - resolved = symbol_resolved_p (add_symbol); - symp->sy_flags.sy_resolving = 0; - goto exit_dont_set_value; - } - else if (finalize_syms - && ((final_seg == expr_section && seg_left != expr_section) - || symbol_shadow_p (symp))) - { - /* If the symbol is an expression symbol, do similarly - as for undefined and common syms above. Handles - "sym +/- expr" where "expr" cannot be evaluated - immediately, and we want relocations to be against - "sym", eg. because it is weak. */ - symp->sy_value.X_op = O_symbol; - symp->sy_value.X_add_symbol = add_symbol; - symp->sy_value.X_add_number = final_val; - symp->sy_value.X_op_symbol = add_symbol; - final_seg = seg_left; final_val += symp->sy_frag->fr_address + left; resolved = symbol_resolved_p (add_symbol); symp->sy_flags.sy_resolving = 0; @@ -1356,7 +1521,7 @@ resolve_symbol_value (symbolS *symp) operands must be absolute. We already handled the case of addition or subtraction of a constant above. This will probably need to be changed for an object file format which - supports arbitrary expressions, such as IEEE-695. */ + supports arbitrary expressions. */ if (!(seg_left == absolute_section && seg_right == absolute_section) && !(op == O_eq || op == O_ne) @@ -2147,14 +2312,14 @@ S_IS_LOCAL (symbolS *s) if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL)) abort (); - if (bfd_get_section (s->bsym) == reg_section) + if (bfd_asymbol_section (s->bsym) == reg_section) return 1; if (flag_strip_local_absolute /* Keep BSF_FILE symbols in order to allow debuggers to identify the source file even when the object file is stripped. */ && (flags & (BSF_GLOBAL | BSF_FILE)) == 0 - && bfd_get_section (s->bsym) == absolute_section) + && bfd_asymbol_section (s->bsym) == absolute_section) return 1; name = S_GET_NAME (s); @@ -2462,12 +2627,8 @@ symbol_set_value_expression (symbolS *s, const expressionS *exp) int symbol_same_p (symbolS *s1, symbolS *s2) { - if (s1->sy_flags.sy_local_symbol - && local_symbol_converted_p ((struct local_symbol *) s1)) - s1 = local_symbol_get_real_symbol ((struct local_symbol *) s1); - if (s2->sy_flags.sy_local_symbol - && local_symbol_converted_p ((struct local_symbol *) s2)) - s2 = local_symbol_get_real_symbol ((struct local_symbol *) s2); + s1 = get_real_sym (s1); + s2 = get_real_sym (s2); return s1 == s2; } @@ -2722,6 +2883,18 @@ symbol_shadow_p (symbolS *s) return s->sy_next == s; } +/* If S was created as a struct symbol, return S, otherwise if S is a + converted local_symbol return the converted symbol, otherwise + return NULL. */ + +symbolS * +symbol_symbolS (symbolS *s) +{ + if (LOCAL_SYMBOL_CHECK (s)) + return NULL; + return s; +} + /* Return the BFD symbol for a symbol. */ asymbol * @@ -3089,7 +3262,7 @@ symbol_relc_make_sym (symbolS * sym) is defined as an expression or a plain value. */ if ( S_GET_SEGMENT (sym) == expr_section || S_GET_SEGMENT (sym) == absolute_section) - return symbol_relc_make_expr (& sym->sy_value); + return symbol_relc_make_expr (symbol_get_value_expression (sym)); /* This may be a "fake symbol", referring to ".". Write out a special null symbol to refer to this position. */