From 321df0656c7557004a232b4ac3d8c354a59de364 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 27 Oct 2015 12:01:55 +1030 Subject: [PATCH] Evaluate __start_* and __stop_* symbol PROVIDE expressions early Makes these symbols defined before bfd_elf_size_dynamic_sections, to avoid horrible hacks elsewhere. The exp_fold_tree undefweak change is necessary to define undefweak symbols early too. The comment was wrong. PROVIDE in fact defines undefweak symbols, via bfd_elf_record_link_assignment. PR ld/19175 * ldlang.c (lang_insert_orphan): Evaluate __start_* and __stop_* symbol PROVIDE expressions. * ldexp.c (exp_fold_tree_1 ): Define undefweak references. --- ld/ChangeLog | 8 ++++++++ ld/ldexp.c | 7 +++++-- ld/ldlang.c | 26 +++++++++++++++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 2cb506a..bef7b26 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2015-10-27 Alan Modra + + PR ld/19175 + * ldlang.c (lang_insert_orphan): Evaluate __start_* and __stop_* + symbol PROVIDE expressions. + * ldexp.c (exp_fold_tree_1 ): Define undefweak + references. + 2015-10-22 H.J. Lu * configure.ac: Properly check diff --git a/ld/ldexp.c b/ld/ldexp.c index 7694f7b..2ec8eb6 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -1126,11 +1126,14 @@ 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_undefweak || h->linker_def)) { /* Do nothing. The symbol was never referenced, or - was defined in some object file. Undefined weak - symbols stay undefined. */ + was defined in some object file. Note that + undefweak symbols are defined by PROVIDE. This + is to support glibc use of __rela_iplt_start and + similar weak references. */ break; } } diff --git a/ld/ldlang.c b/ld/ldlang.c index 2986981..5c7ea9f 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1805,6 +1805,7 @@ lang_insert_orphan (asection *s, { lang_statement_list_type add; const char *ps; + lang_assignment_statement_type *start_assign; lang_output_section_statement_type *os; lang_output_section_statement_type **os_tail; @@ -1827,6 +1828,7 @@ lang_insert_orphan (asection *s, NULL, NULL, NULL, constraint, 0); ps = NULL; + start_assign = NULL; if (config.build_constructors && *os_tail == os) { /* If the name of the section is representable in C, then create @@ -1841,9 +1843,10 @@ lang_insert_orphan (asection *s, symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1); symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd); sprintf (symname + (symname[0] != 0), "__start_%s", secname); - lang_add_assignment (exp_provide (symname, - exp_nameop (NAME, "."), - FALSE)); + start_assign + = lang_add_assignment (exp_provide (symname, + exp_nameop (NAME, "."), + FALSE)); } } @@ -1866,16 +1869,25 @@ lang_insert_orphan (asection *s, lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL, NULL); - if (ps != NULL && *ps == '\0') + if (start_assign != NULL) { char *symname; + lang_assignment_statement_type *stop_assign; + bfd_vma dot; symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1); symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd); sprintf (symname + (symname[0] != 0), "__stop_%s", secname); - lang_add_assignment (exp_provide (symname, - exp_nameop (NAME, "."), - FALSE)); + stop_assign + = lang_add_assignment (exp_provide (symname, + exp_nameop (NAME, "."), + FALSE)); + /* Evaluate the expression to define the symbol if referenced, + before sizing dynamic sections. */ + dot = os->bfd_section->vma; + exp_fold_tree (start_assign->exp, os->bfd_section, &dot); + dot += s->size; + exp_fold_tree (stop_assign->exp, os->bfd_section, &dot); } /* Restore the global list pointer. */ -- 2.7.4