aboutsummaryrefslogtreecommitdiff
path: root/gas/symbols.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-04-24 11:26:51 +0930
committerAlan Modra <amodra@gmail.com>2019-04-24 23:00:17 +0930
commit1903f1385bff910861942743860d8577423bcb6c (patch)
tree64da109ffb42c711b2c37b4dc24f37ccbe19c876 /gas/symbols.c
parenta679f24ecc00ff7df02c5e6e4804fc9f19cbe595 (diff)
downloadgdb-1903f1385bff910861942743860d8577423bcb6c.zip
gdb-1903f1385bff910861942743860d8577423bcb6c.tar.gz
gdb-1903f1385bff910861942743860d8577423bcb6c.tar.bz2
resolve_symbol_value vs. .loc view resolution
In most cases we don't want expression symbols, such as that created for an expression like "symbol + (1f - .)", resolved down to a constant. Instead we'd like to leave the expression as "symbol + constant" once the "1f - ." part has been resolved, and let the backend decide whether "symbol" can be reduced further. However, that doesn't work when trying to resolve .loc view symbols early. We get expression symbols left as an O_symbol expression pointing at an absolute symbol, and marked as sy_flags.sy_resolved. That wouldn't really be a problem, but when one of those expression symbols is used in further .loc view expressions, its value is taken as zero. This patch fixes the symbol value mistake, and stops creation of O_symbol expression symbols pointing to absolute symbols. Either of these fixes would cure the .loc view usage. PR 24444 * symbols.c (resolve_symbol_value): When handling symbols marked as sy_flags.resolved, return correct value for the case of expression symbols left as an O_symbol expression. Merge O_symbol code handling undefined and common symbols with code handling special cases of expression symbols. Use seg_left to test for undefined and common symbols. Don't leave an O_symbol expression when X_add_symbol resolves to the absolute_section. Init final_val later. * testsuite/gas/mmix/basep-7.d: Adjust expected output.
Diffstat (limited to 'gas/symbols.c')
-rw-r--r--gas/symbols.c43
1 files changed, 19 insertions, 24 deletions
diff --git a/gas/symbols.c b/gas/symbols.c
index d8a9c92..9786795 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -1221,7 +1221,7 @@ valueT
resolve_symbol_value (symbolS *symp)
{
int resolved;
- valueT final_val = 0;
+ valueT final_val;
segT final_seg;
if (LOCAL_SYMBOL_CHECK (symp))
@@ -1245,10 +1245,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;
@@ -1305,6 +1313,7 @@ resolve_symbol_value (symbolS *symp)
resolved = 1;
}
+ final_val = 0;
final_seg = undefined_section;
goto exit_dont_set_value;
}
@@ -1392,11 +1401,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)
{
@@ -1407,25 +1421,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;