From 422f1c65c9e9d30a7e82d136b2d4c6cd901f0245 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 22 Dec 2014 11:11:50 +1030 Subject: [PATCH] Report an error for script multiply defined symbols or maybe not just yet, but this is better than a FIXME. * ldexp.c (update_definedness): Return false if script symbol is redefining a strong symbol in an object. (exp_fold_tree_1 ): Set up for reporting a multiple definition error, but for now leave disabled. --- ld/ChangeLog | 7 +++++++ ld/ldexp.c | 36 +++++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 7f6eca2..154def7 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,12 @@ 2014-12-23 Alan Modra + * ldexp.c (update_definedness): Return false if script symbol is + redefining a strong symbol in an object. + (exp_fold_tree_1 ): Set up for reporting a multiple + definition error, but for now leave disabled. + +2014-12-23 Alan Modra + * ldexp.c (exp_fold_tree_1 ): Test linker_def. 2014-12-23 Alan Modra diff --git a/ld/ldexp.c b/ld/ldexp.c index b4af893..bd2266b 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -291,11 +291,13 @@ symbol_defined (const char *name) bfd_hash_lookup (&definedness_table, name, FALSE, FALSE)); } -/* Update the definedness state of NAME. */ +/* Update the definedness state of NAME. Return FALSE if script symbol + is multiply defining a strong symbol in an object. */ -static void +static bfd_boolean update_definedness (const char *name, struct bfd_link_hash_entry *h) { + bfd_boolean ret; struct definedness_hash_entry *defentry = (struct definedness_hash_entry *) bfd_hash_lookup (&definedness_table, name, TRUE, FALSE); @@ -305,14 +307,22 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h) /* If the symbol was already defined, and not by a script, then it must be defined by an object file or by the linker target code. */ + ret = TRUE; if (!defentry->by_script && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak || h->type == bfd_link_hash_common)) - defentry->by_object = 1; + { + defentry->by_object = 1; + if (h->type == bfd_link_hash_defined + && h->u.def.section->output_section != NULL + && !h->linker_def) + ret = FALSE; + } defentry->by_script = 1; defentry->iteration = lang_statement_iteration; + return ret; } static void @@ -1108,19 +1118,27 @@ exp_fold_tree_1 (etree_type *tree) tree->assign.dst); } - /* FIXME: Should we worry if the symbol is already - defined? */ - update_definedness (tree->assign.dst, h); - h->type = bfd_link_hash_defined; - h->u.def.value = expld.result.value; if (expld.result.section == NULL) expld.result.section = expld.section; + if (!update_definedness (tree->assign.dst, h) && 0) + { + /* Symbol was already defined. For now this error + is disabled because it causes failures in the ld + testsuite: ld-elf/var1, ld-scripts/defined5, and + ld-scripts/pr14962. Some of these no doubt + reflect scripts used in the wild. */ + (*link_info.callbacks->multiple_definition) + (&link_info, h, link_info.output_bfd, + expld.result.section, expld.result.value); + } + h->type = bfd_link_hash_defined; + h->u.def.value = expld.result.value; h->u.def.section = expld.result.section; if (tree->type.node_class == etree_provide) tree->type.node_class = etree_provided; /* Copy the symbol type if this is a simple assignment of - one symbol to another. This could be more general + one symbol to another. This could be more general (e.g. a ?: operator with NAMEs in each branch). */ if (tree->assign.src->type.node_class == etree_name) { -- 2.7.4