X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fsymbols.c;h=40888379de82be16663424608c0567647448e243;hb=514cd3a0f589fa48ca7bc9504c36436c0cbefcb2;hp=0d5a85440938d897cefdddee505d4cce80594a77;hpb=29a2809e4210d5055291e95de861b493c55b9c0a;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/symbols.c b/gas/symbols.c index 0d5a854409..40888379de 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -1,5 +1,5 @@ /* symbols.c -symbol table- - Copyright (C) 1987-2016 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -25,6 +25,7 @@ #include "obstack.h" /* For "symbols.h" */ #include "subsegs.h" #include "struc-symbol.h" +#include "write.h" /* This is non-zero if symbols are case sensitive, which is the default. */ @@ -107,6 +108,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); @@ -262,7 +264,7 @@ define_sym_at_dot (symbolS *symbolP) symbolS * colon (/* Just seen "x:" - rattle symbols & frags. */ - const char *sym_name /* Symbol name, as a cannonical string. */ + const char *sym_name /* Symbol name, as a canonical string. */ /* We copy this string: OK to alter later. */) { symbolS *symbolP; /* Symbol we are working with. */ @@ -406,8 +408,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]; @@ -1355,7 +1356,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) @@ -1429,7 +1430,16 @@ resolve_symbol_value (symbolS *symp) case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; case O_logical_and: left = left && right; break; case O_logical_or: left = left || right; break; - default: abort (); + + case O_illegal: + case O_absent: + case O_constant: + /* See PR 20895 for a reproducer. */ + as_bad (_("Invalid operation on symbol")); + goto exit_dont_set_value; + + default: + abort (); } final_val += symp->sy_frag->fr_address + left; @@ -1541,7 +1551,7 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP) case O_register: if (!symbol_equated_p (symbolP)) break; - /* Fall thru. */ + /* Fallthru. */ case O_symbol: case O_symbol_rva: symbolP = exp.X_add_symbol; @@ -1552,9 +1562,23 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP) } *symbolPP = symbolP; - *valueP = exp.X_add_number; - *segP = symbolP->bsym->section; - *fragPP = symbolP->sy_frag; + + /* A bogus input file can result in resolve_expression() + generating a local symbol, so we have to check again. */ + if (LOCAL_SYMBOL_CHECK (symbolP)) + { + struct local_symbol *locsym = (struct local_symbol *) symbolP; + + *valueP = locsym->lsy_value; + *segP = locsym->lsy_section; + *fragPP = local_symbol_get_frag (locsym); + } + else + { + *valueP = exp.X_add_number; + *segP = symbolP->bsym->section; + *fragPP = symbolP->sy_frag; + } if (*segP == expr_section) switch (exp.X_op) @@ -1639,7 +1663,7 @@ define_dollar_label (long label) { dollar_labels = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY); dollar_label_instances = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY); - dollar_label_defines = (char *) xmalloc (DOLLAR_LABEL_BUMP_BY); + dollar_label_defines = XNEWVEC (char, DOLLAR_LABEL_BUMP_BY); dollar_label_max = DOLLAR_LABEL_BUMP_BY; dollar_label_count = 0; } @@ -1649,7 +1673,8 @@ define_dollar_label (long label) dollar_labels = XRESIZEVEC (long, dollar_labels, dollar_label_max); dollar_label_instances = XRESIZEVEC (long, dollar_label_instances, dollar_label_max); - dollar_label_defines = (char *) xrealloc (dollar_label_defines, dollar_label_max); + dollar_label_defines = XRESIZEVEC (char, dollar_label_defines, + dollar_label_max); } /* if we needed to grow */ dollar_labels[dollar_label_count] = label; @@ -1660,7 +1685,7 @@ define_dollar_label (long label) /* Caller must copy returned name: we re-use the area for the next name. - The mth occurence of label n: is turned into the symbol "Ln^Am" + The mth occurrence of label n: is turned into the symbol "Ln^Am" where n is the label number and m is the instance number. "L" makes it a label discarded unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the same name as a local label @@ -1825,7 +1850,7 @@ fb_label_instance (long label) /* Caller must copy returned name: we re-use the area for the next name. - The mth occurence of label n: is turned into the symbol "Ln^Bm" + The mth occurrence of label n: is turned into the symbol "Ln^Bm" where n is the label number and m is the instance number. "L" makes it a label discarded unless debugging and "^B"('\2') ensures no ordinary symbol SHOULD get the same name as a local label @@ -2081,16 +2106,20 @@ S_IS_DEFINED (symbolS *s) int S_FORCE_RELOC (symbolS *s, int strict) { + segT sec; if (LOCAL_SYMBOL_CHECK (s)) - return ((struct local_symbol *) s)->lsy_section == undefined_section; - - return ((strict + sec = ((struct local_symbol *) s)->lsy_section; + else + { + if ((strict && ((s->bsym->flags & BSF_WEAK) != 0 || (EXTERN_FORCE_RELOC && (s->bsym->flags & BSF_GLOBAL) != 0))) - || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0 - || s->bsym->section == undefined_section - || bfd_is_com_section (s->bsym->section)); + || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0) + return TRUE; + sec = s->bsym->section; + } + return bfd_is_und_section (sec) || bfd_is_com_section (sec); } int @@ -2133,6 +2162,9 @@ S_IS_LOCAL (symbolS *s) && ! S_IS_DEBUG (s) && (strchr (name, DOLLAR_LABEL_CHAR) || strchr (name, LOCAL_LABEL_CHAR) +#if FAKE_LABEL_CHAR != DOLLAR_LABEL_CHAR + || strchr (name, FAKE_LABEL_CHAR) +#endif || TC_LABEL_IS_LOCAL (name) || (! flag_keep_locals && (bfd_is_local_label (stdoutput, s->bsym) @@ -3059,7 +3091,7 @@ symbol_relc_make_sym (symbolS * sym) || S_GET_SEGMENT (sym) == absolute_section) return symbol_relc_make_expr (& sym->sy_value); - /* This may be a "fake symbol" L0\001, referring to ".". + /* This may be a "fake symbol", referring to ".". Write out a special null symbol to refer to this position. */ if (! strcmp (S_GET_NAME (sym), FAKE_LABEL_NAME)) return xstrdup ("."); @@ -3075,11 +3107,11 @@ symbol_relc_make_sym (symbolS * sym) sname_len = strlen (sname); typetag = symbol_section_p (sym) ? 'S' : 's'; - terminal = xmalloc (1 /* S or s */ - + 8 /* sname_len in decimal */ - + 1 /* _ spacer */ - + sname_len /* name itself */ - + 1 /* \0 */ ); + terminal = XNEWVEC (char, (1 /* S or s */ + + 8 /* sname_len in decimal */ + + 1 /* _ spacer */ + + sname_len /* name itself */ + + 1 /* \0 */ )); sprintf (terminal, "%c%d:%s", typetag, sname_len, sname); return terminal;