/* symbols.c -symbol table-
- Copyright (C) 1987-2019 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
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
/* 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.
+ the first field which is present in both structs.
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
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;
+ return symbol_temp_new (now_seg, frag_now_fix_octets (), frag_now);
}
symbolS *
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:
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)
{
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)
+ while (symp->sy_value.X_op == O_symbol)
{
final_val += symp->sy_value.X_add_number;
symp = symp->sy_value.X_add_symbol;
+ if (LOCAL_SYMBOL_CHECK (symp))
+ {
+ struct local_symbol *locsym = (struct local_symbol *) symp;
+ final_val += locsym->lsy_value;
+ return final_val;
+ }
+ if (!symp->sy_flags.sy_resolved)
+ return 0;
}
if (symp->sy_value.X_op == O_constant)
final_val += symp->sy_value.X_add_number;
/* Fall through. */
case O_constant:
- if (symp->sy_flags.sy_octets)
+ /* 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;
break;
}
+ /* Don't leave symbol loops. */
+ if (finalize_syms
+ && add_symbol->sy_flags.sy_resolving)
+ break;
+
if (finalize_syms && final_val == 0)
{
if (LOCAL_SYMBOL_CHECK (add_symbol))
if (finalize_syms)
S_SET_VALUE (symp, final_val);
-exit_dont_set_value:
+ exit_dont_set_value:
/* Always set the segment, even if not finalizing the value.
The segment is used to determine whether a symbol is defined. */
S_SET_SEGMENT (symp, final_seg);
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);
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
/* 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", referring to ".".
Write out a special null symbol to refer to this position. */