diff options
author | Alan Modra <amodra@gmail.com> | 2015-10-27 12:01:55 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2015-10-27 12:54:59 +1030 |
commit | 321df0656c7557004a232b4ac3d8c354a59de364 (patch) | |
tree | 3aec2b2461c111ac10685f16931e7a7fe5757aae /ld/ldlang.c | |
parent | d7f3ff3ea7830389f458be7c5eadb5d4a4e0a90b (diff) | |
download | gdb-321df0656c7557004a232b4ac3d8c354a59de364.zip gdb-321df0656c7557004a232b4ac3d8c354a59de364.tar.gz gdb-321df0656c7557004a232b4ac3d8c354a59de364.tar.bz2 |
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 <etree_provide>): Define undefweak
references.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 26 |
1 files changed, 19 insertions, 7 deletions
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. */ |