summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/ld/ldexp.c
diff options
context:
space:
mode:
authorAndrew Hsieh <andrewhsieh@google.com>2014-12-09 17:57:18 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2014-12-09 19:50:14 +0800
commit5e8c1cf25beccac1d22d10dc866912394f42771b (patch)
treeee16b70f804484dc8e434e647e699ab50da2620f /binutils-2.25/ld/ldexp.c
parent8eebd7953384e6662ca926b003f2cdda8ccd3ee5 (diff)
downloadtoolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.zip
toolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.tar.gz
toolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.tar.bz2
[2.25] sync to a30720e3e633f275250e26f85ccae5dbdddfb6c6
local patches will be re-applied later commit a30720e3e633f275250e26f85ccae5dbdddfb6c6 Author: Alan Modra <amodra@gmail.com> Date: Wed Nov 19 10:30:16 2014 +1030 daily update Change-Id: Ieb2a3f4dd2ecb289ac5305ff08d428b2847494ab
Diffstat (limited to 'binutils-2.25/ld/ldexp.c')
-rw-r--r--binutils-2.25/ld/ldexp.c135
1 files changed, 125 insertions, 10 deletions
diff --git a/binutils-2.25/ld/ldexp.c b/binutils-2.25/ld/ldexp.c
index 49e7c65..5c4f8dd 100644
--- a/binutils-2.25/ld/ldexp.c
+++ b/binutils-2.25/ld/ldexp.c
@@ -1,5 +1,5 @@
/* This module handles expression trees.
- Copyright 1991-2013 Free Software Foundation, Inc.
+ Copyright (C) 1991-2014 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
This file is part of the GNU Binutils.
@@ -575,13 +575,10 @@ fold_name (etree_type *tree)
break;
case DEFINED:
- if (expld.phase == lang_first_phase_enum)
- lang_track_definedness (tree->name.name);
- else
+ if (expld.phase != lang_first_phase_enum)
{
struct bfd_link_hash_entry *h;
- int def_iteration
- = lang_symbol_definition_iteration (tree->name.name);
+ struct lang_definedness_hash_entry *def;
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info,
@@ -591,15 +588,33 @@ fold_name (etree_type *tree)
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_common)
- && (def_iteration == lang_statement_iteration
- || def_iteration == -1));
+ && ((def = lang_symbol_defined (tree->name.name)) == NULL
+ || def->by_object
+ || def->iteration == (lang_statement_iteration & 1)));
}
break;
case NAME:
if (expld.assign_name != NULL
&& strcmp (expld.assign_name, tree->name.name) == 0)
- expld.assign_name = NULL;
+ {
+ /* Self-assignment is only allowed for absolute symbols
+ defined in a linker script. */
+ struct bfd_link_hash_entry *h;
+ struct lang_definedness_hash_entry *def;
+
+ h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info,
+ tree->name.name,
+ FALSE, FALSE, TRUE);
+ if (!(h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section == bfd_abs_section_ptr
+ && (def = lang_symbol_defined (tree->name.name)) != NULL
+ && def->iteration == (lang_statement_iteration & 1)))
+ expld.assign_name = NULL;
+ }
if (expld.phase == lang_first_phase_enum)
;
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
@@ -775,6 +790,89 @@ fold_name (etree_type *tree)
}
}
+/* Return true if TREE is '.'. */
+
+static bfd_boolean
+is_dot (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_name
+ && tree->type.node_code == NAME
+ && tree->name.name[0] == '.'
+ && tree->name.name[1] == 0);
+}
+
+/* Return true if TREE is a constant equal to VAL. */
+
+static bfd_boolean
+is_value (const etree_type *tree, bfd_vma val)
+{
+ return (tree->type.node_class == etree_value
+ && tree->value.value == val);
+}
+
+/* Return true if TREE is an absolute symbol equal to VAL defined in
+ a linker script. */
+
+static bfd_boolean
+is_sym_value (const etree_type *tree, bfd_vma val)
+{
+ struct bfd_link_hash_entry *h;
+ struct lang_definedness_hash_entry *def;
+
+ return (tree->type.node_class == etree_name
+ && tree->type.node_code == NAME
+ && (def = lang_symbol_defined (tree->name.name)) != NULL
+ && def->by_script
+ && def->iteration == (lang_statement_iteration & 1)
+ && (h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info,
+ tree->name.name,
+ FALSE, FALSE, TRUE)) != NULL
+ && h->type == bfd_link_hash_defined
+ && h->u.def.section == bfd_abs_section_ptr
+ && h->u.def.value == val);
+}
+
+/* Return true if TREE is ". != 0". */
+
+static bfd_boolean
+is_dot_ne_0 (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_binary
+ && tree->type.node_code == NE
+ && is_dot (tree->binary.lhs)
+ && is_value (tree->binary.rhs, 0));
+}
+
+/* Return true if TREE is ". = . + 0" or ". = . + sym" where sym is an
+ absolute constant with value 0 defined in a linker script. */
+
+static bfd_boolean
+is_dot_plus_0 (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_binary
+ && tree->type.node_code == '+'
+ && is_dot (tree->binary.lhs)
+ && (is_value (tree->binary.rhs, 0)
+ || is_sym_value (tree->binary.rhs, 0)));
+}
+
+/* Return true if TREE is "ALIGN (. != 0 ? some_expression : 1)". */
+
+static bfd_boolean
+is_align_conditional (const etree_type *tree)
+{
+ if (tree->type.node_class == etree_unary
+ && tree->type.node_code == ALIGN_K)
+ {
+ tree = tree->unary.child;
+ return (tree->type.node_class == etree_trinary
+ && is_dot_ne_0 (tree->trinary.cond)
+ && is_value (tree->trinary.rhs, 1));
+ }
+ return 0;
+}
+
static void
exp_fold_tree_1 (etree_type *tree)
{
@@ -839,6 +937,20 @@ exp_fold_tree_1 (etree_type *tree)
exp_fold_tree_1 (tree->assign.src);
expld.assigning_to_dot = FALSE;
+ /* If we are assigning to dot inside an output section
+ arrange to keep the section, except for certain
+ expressions that evaluate to zero. We ignore . = 0,
+ . = . + 0, and . = ALIGN (. != 0 ? expr : 1). */
+ if (expld.phase == lang_mark_phase_enum
+ && expld.section != bfd_abs_section_ptr
+ && !(expld.result.valid_p
+ && expld.result.value == 0
+ && (is_value (tree->assign.src, 0)
+ || is_sym_value (tree->assign.src, 0)
+ || is_dot_plus_0 (tree->assign.src)
+ || is_align_conditional (tree->assign.src))))
+ expld.section->flags |= SEC_KEEP;
+
if (!expld.result.valid_p)
{
if (expld.phase != lang_mark_phase_enum)
@@ -889,7 +1001,10 @@ exp_fold_tree_1 (etree_type *tree)
if (h == NULL
|| (h->type != bfd_link_hash_new
&& h->type != bfd_link_hash_undefined
- && h->type != bfd_link_hash_common))
+ && h->type != bfd_link_hash_common
+ && !(h->type == bfd_link_hash_defined
+ && (h->u.def.section->flags
+ & SEC_LINKER_CREATED) != 0)))
{
/* Do nothing. The symbol was never referenced, or was
defined by some object. */