This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] Properly convert address load of __start_XXX/__stop_XXX
- From: Alan Modra <amodra at gmail dot com>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: Binutils <binutils at sourceware dot org>
- Date: Tue, 27 Oct 2015 12:54:21 +1030
- Subject: Re: [PATCH] Properly convert address load of __start_XXX/__stop_XXX
- Authentication-results: sourceware.org; auth=none
- References: <1445864414-32680-1-git-send-email-hjl dot tools at gmail dot com> <CAMe9rOpFHo+8-mw4A7c3tE0J4W2jbdM0gu7usqjC3W2mzOVqeQ at mail dot gmail dot com>
On Mon, Oct 26, 2015 at 08:17:44AM -0700, H.J. Lu wrote:
+bfd_boolean
> +bfd_link_get_defined_symbol (struct bfd_link_info *info,
> + struct bfd_link_hash_entry *h,
> + asection **sec, bfd_vma *value)
I think we can do better than this inelegant solution. The underlying
problem is that the linker does not define __start_* and __stop_*
before sizing dynamic sections. Orphan sections are placed before
sizing dynamic sections, but lang_insert_orphan arranges to define
the symbols by adding script PROVIDE statements, and these are not
evaluated until later.
So it ought to be a simple matter of evaluating those PROVIDE
statements.
Ah, I see you have already reverted bfd_link_get_defined_symbol.
This patch should mean you don't need the bfd_link_hash_new checks.
commit 6762151f758394fe2550760f6fd6fb5748a59b33
Author: Alan Modra <amodra@gmail.com>
Date: Tue Oct 27 12:01:55 2015 +1030
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.
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
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. */
--
Alan Modra
Australia Development Lab, IBM