diff options
-rw-r--r-- | ld/ChangeLog | 8 | ||||
-rw-r--r-- | ld/ldexp.c | 7 | ||||
-rw-r--r-- | 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 <amodra@gmail.com> + + PR ld/19175 + * ldlang.c (lang_insert_orphan): Evaluate __start_* and __stop_* + symbol PROVIDE expressions. + * ldexp.c (exp_fold_tree_1 <etree_provide>): Define undefweak + references. + 2015-10-22 H.J. Lu <hongjiu.lu@intel.com> * configure.ac: Properly check @@ -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. */ |