/* symbols.c -symbol table-
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#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;
+
+ /* This if set if the unit of the symbol value is "octets" instead
+ of "bytes". */
+ unsigned int sy_octets : 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. */
const char * an_external_name;
#endif
-static char *save_symbol_name (const char *);
+static const char *save_symbol_name (const char *);
static void fb_label_init (void);
static long dollar_label_instance (long);
static long fb_label_instance (long);
/* Save a symbol name on a permanent obstack, and convert it according
to the object file format. */
-static char *
+static const char *
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);
valueT valu, /* Symbol value. */
fragS *frag /* Associated fragment. */)
{
- char *preserved_copy_of_name;
+ const char *preserved_copy_of_name;
symbolS *symbolP;
preserved_copy_of_name = save_symbol_name (name);
struct local_symbol *
local_symbol_make (const char *name, segT section, valueT val, fragS *frag)
{
- char *name_copy;
+ const char *name_copy;
struct local_symbol *ret;
++local_symbol_count;
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. */)
{
- register symbolS *symbolP; /* Symbol we are working with. */
+ symbolS *symbolP; /* Symbol we are working with. */
/* Sun local labels go out of scope whenever a non-local symbol is
defined. */
}
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];
void
symbol_table_insert (symbolS *symbolP)
{
- register const char *error_string;
+ const char *error_string;
know (symbolP);
know (S_GET_NAME (symbolP));
symbolS *
symbol_find_or_make (const char *name)
{
- register symbolS *symbolP;
+ symbolS *symbolP;
symbolP = symbol_find (name);
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 *
{
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;
}
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)
{
return symbol_temp_new (now_seg, frag_now_fix (), frag_now);
}
+symbolS *
+symbol_temp_new_now_octets (void)
+{
+ symbolS * symb = symbol_temp_new (now_seg, frag_now_fix_octets (), frag_now);
+ symb->sy_flags.sy_octets = 1;
+ return symb;
+}
+
symbolS *
symbol_temp_make (void)
{
symbolS *
symbol_find_noref (const char *name, int noref)
{
+ symbolS * result;
+ char * copy = NULL;
+
#ifdef tc_canonicalize_symbol_name
{
- char *copy;
- size_t len = strlen (name) + 1;
-
- copy = (char *) alloca (len);
- memcpy (copy, name, len);
+ copy = xstrdup (name);
name = tc_canonicalize_symbol_name (copy);
}
#endif
if (! symbols_case_sensitive)
{
- char *copy;
const char *orig;
+ char *copy2 = NULL;
unsigned char c;
orig = name;
- name = copy = (char *) alloca (strlen (name) + 1);
+ if (copy != NULL)
+ copy2 = copy;
+ name = copy = XNEWVEC (char, strlen (name) + 1);
while ((c = *orig++) != '\0')
- {
- *copy++ = TOUPPER (c);
- }
+ *copy++ = TOUPPER (c);
*copy = '\0';
+
+ if (copy2 != NULL)
+ free (copy2);
+ copy = (char *) name;
}
- return symbol_find_exact_noref (name, noref);
+ result = symbol_find_exact_noref (name, noref);
+ if (copy != NULL)
+ free (copy);
+ return result;
}
/* Once upon a time, symbols were kept in a singly linked list. At
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
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:
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:
static void
report_op_error (symbolS *symp, symbolS *left, operatorT op, symbolS *right)
{
- char *file;
+ const char *file;
unsigned int line;
segT seg_left = left ? S_GET_SEGMENT (left) : 0;
segT seg_right = S_GET_SEGMENT (right);
resolve_symbol_value (symbolS *symp)
{
int resolved;
- valueT final_val = 0;
+ valueT final_val;
segT final_seg;
if (LOCAL_SYMBOL_CHECK (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;
resolved = 1;
}
+ final_val = 0;
final_seg = undefined_section;
goto exit_dont_set_value;
}
/* Fall through. */
case O_constant:
- final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
+ if (symp->sy_flags.sy_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. */
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)
{
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;
resolved = symbol_resolved_p (add_symbol);
if (S_IS_WEAKREFR (symp))
- goto exit_dont_set_value;
+ {
+ symp->sy_flags.sy_resolving = 0;
+ goto exit_dont_set_value;
+ }
break;
case O_uminus:
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)
already issued a warning about using a bad symbol. */
if (seg_right == absolute_section && finalize_syms)
{
- char *file;
+ const char *file;
unsigned int line;
if (expr_symbol_where (symp, &file, &line))
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;
case O_register:
if (!symbol_equated_p (symbolP))
break;
- /* Fall thru. */
+ /* Fallthru. */
case O_symbol:
case O_symbol_rva:
symbolP = exp.X_add_symbol;
}
*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)
if (dollar_labels == NULL)
{
- dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
- dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
- dollar_label_defines = (char *) xmalloc (DOLLAR_LABEL_BUMP_BY);
+ dollar_labels = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY);
+ dollar_label_instances = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY);
+ dollar_label_defines = XNEWVEC (char, DOLLAR_LABEL_BUMP_BY);
dollar_label_max = DOLLAR_LABEL_BUMP_BY;
dollar_label_count = 0;
}
else if (dollar_label_count == dollar_label_max)
{
dollar_label_max += DOLLAR_LABEL_BUMP_BY;
- dollar_labels = (long *) xrealloc ((char *) dollar_labels,
- dollar_label_max * sizeof (long));
- dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
- dollar_label_max * sizeof (long));
- dollar_label_defines = (char *) xrealloc (dollar_label_defines, dollar_label_max);
+ dollar_labels = XRESIZEVEC (long, dollar_labels, dollar_label_max);
+ dollar_label_instances = XRESIZEVEC (long, dollar_label_instances,
+ 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;
/* 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
of ^A. */
char * /* Return local label name. */
-dollar_label_name (register long n, /* we just saw "n$:" : n a number. */
- register int augend /* 0 for current instance, 1 for new instance. */)
+dollar_label_name (long n, /* we just saw "n$:" : n a number. */
+ int augend /* 0 for current instance, 1 for new instance. */)
{
long i;
/* Returned to caller, then copied. Used for created names ("4f"). */
static char symbol_name_build[24];
- register char *p;
- register char *q;
+ char *p;
+ char *q;
char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */
know (n >= 0);
if (fb_labels == NULL)
{
- fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
- fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
+ fb_labels = XNEWVEC (long, FB_LABEL_BUMP_BY);
+ fb_label_instances = XNEWVEC (long, FB_LABEL_BUMP_BY);
fb_label_max = FB_LABEL_BUMP_BY;
fb_label_count = FB_LABEL_SPECIAL;
else if (fb_label_count == fb_label_max)
{
fb_label_max += FB_LABEL_BUMP_BY;
- fb_labels = (long *) xrealloc ((char *) fb_labels,
- fb_label_max * sizeof (long));
- fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
- fb_label_max * sizeof (long));
+ fb_labels = XRESIZEVEC (long, fb_labels, fb_label_max);
+ fb_label_instances = XRESIZEVEC (long, fb_label_instances, fb_label_max);
} /* if we needed to grow */
fb_labels[fb_label_count] = 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
long i;
/* Returned to caller, then copied. Used for created names ("4f"). */
static char symbol_name_build[24];
- register char *p;
- register char *q;
+ char *p;
+ char *q;
char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */
know (n >= 0);
char *symbol_decode;
int label_number;
int instance_number;
- char *type;
+ const char *type;
const char *message_format;
int lindex = 0;
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
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);
&& ! 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)
}
if (s->bsym->flags & BSF_SECTION_SYM)
{
- char * file;
- unsigned int line;
-
/* Do not reassign section symbols. */
- as_where (& file, & line);
- as_warn_where (file, line,
- _("section symbols are already global"));
+ as_warn (_("section symbols are already global"));
return;
}
#ifndef TC_GLOBAL_REGISTER_SYMBOL_OK
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;
}
symbol_set_frag (sym, frag_now);
}
+/* Set the value of SYM to the current position in the current segment,
+ in octets. */
+
+void
+symbol_set_value_now_octets (symbolS *sym)
+{
+ S_SET_SEGMENT (sym, now_seg);
+ S_SET_VALUE (sym, frag_now_fix_octets ());
+ symbol_set_frag (sym, frag_now);
+ sym->sy_flags.sy_octets = 1;
+}
+
/* Set the frag of a symbol. */
void
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 *
/* else XXX - What do we do now ? */
}
+/* Return whether symbol unit is "octets" (instead of "bytes"). */
+
+int symbol_octets_p (symbolS *s)
+{
+ return s->sy_flags.sy_octets;
+}
+
#ifdef OBJ_SYMFIELD_TYPE
/* Get a pointer to the object format information for a symbol. */
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" 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 (".");
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;
char *
symbol_relc_make_value (offsetT val)
{
- char * terminal = xmalloc (28); /* Enough for long long. */
+ char * terminal = XNEWVEC (char, 28); /* Enough for long long. */
terminal[0] = '#';
bfd_sprintf_vma (stdoutput, terminal + 1, val);
char *
symbol_relc_make_expr (expressionS * exp)
{
- char * opstr = NULL; /* Operator prefix string. */
+ const char * opstr = NULL; /* Operator prefix string. */
int arity = 0; /* Arity of this operator. */
char * operands[3]; /* Up to three operands. */
char * concat_string = NULL;
if (opstr == NULL)
concat_string = NULL;
+ else if (arity == 0)
+ concat_string = xstrdup (opstr);
+ else if (arity == 1)
+ concat_string = concat (opstr, ":", operands[0], (char *) NULL);
+ else if (arity == 2)
+ concat_string = concat (opstr, ":", operands[0], ":", operands[1],
+ (char *) NULL);
else
- {
- /* Allocate new string; include inter-operand padding gaps etc. */
- concat_string = xmalloc (strlen (opstr)
- + 1
- + (arity >= 1 ? (strlen (operands[0]) + 1 ) : 0)
- + (arity >= 2 ? (strlen (operands[1]) + 1 ) : 0)
- + (arity >= 3 ? (strlen (operands[2]) + 0 ) : 0)
- + 1);
- gas_assert (concat_string != NULL);
-
- /* Format the thing. */
- sprintf (concat_string,
- (arity == 0 ? "%s" :
- arity == 1 ? "%s:%s" :
- arity == 2 ? "%s:%s:%s" :
- /* arity == 3 */ "%s:%s:%s:%s"),
- opstr, operands[0], operands[1], operands[2]);
- }
+ concat_string = concat (opstr, ":", operands[0], ":", operands[1], ":",
+ operands[2], (char *) NULL);
/* Free operand strings (not opstr). */
if (arity >= 1) xfree (operands[0]);