This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [RFC][PATCH] Check ELF relocs after opening all all input files
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Alan Modra <amodra at gmail dot com>
- Cc: Nick Clifton <nickc at redhat dot com>, Binutils <binutils at sourceware dot org>
- Date: Thu, 28 Apr 2016 10:11:11 -0700
- Subject: Re: [RFC][PATCH] Check ELF relocs after opening all all input files
- Authentication-results: sourceware.org; auth=none
- References: <20160419134956 dot GA12310 at intel dot com> <57165642 dot 1070808 at redhat dot com> <CAMe9rOrydGcortz2AsujVSQYZCRbSPsi7CFQRnA6ZZiicbUvTA at mail dot gmail dot com> <20160419232457 dot GB20119 at bubble dot grove dot modra dot org> <CAMe9rOqAmmgni51d349yEcW7OcHKq3cPQ3btsJUGR5i_P4uErA at mail dot gmail dot com> <CAMe9rOrCzys1EUwvkYNHjzN8NVxab66WvhUFANXxtb6vxppgXA at mail dot gmail dot com> <20160427022922 dot GA20333 at bubble dot grove dot modra dot org> <CAMe9rOoScOY3U4vSjn8Q22SR6YUh0rhXaO7wvVGvfW+ctc_wew at mail dot gmail dot com> <20160428011151 dot GB18915 at bubble dot grove dot modra dot org> <CAMe9rOrNArE9iqYfUzoWr+OjgsRSkKhw7ULp77JbZOBCz4MAKw at mail dot gmail dot com> <20160428130707 dot GC18915 at bubble dot grove dot modra dot org> <CAMe9rOoPyp29uJouD-rCh+7-ieq_Wx6UPg3beF=x14=Wr7BJuQ at mail dot gmail dot com> <CAMe9rOo0WccDn4zc0Y2-OiLNWiO=vhuwNs5NCW4cb-9F8nvSJQ at mail dot gmail dot com>
On Thu, Apr 28, 2016 at 6:40 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Apr 28, 2016 at 6:09 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Thu, Apr 28, 2016 at 6:07 AM, Alan Modra <amodra@gmail.com> wrote:
>>> On Thu, Apr 28, 2016 at 05:49:57AM -0700, H.J. Lu wrote:
>>>> On Wed, Apr 27, 2016 at 6:11 PM, Alan Modra <amodra@gmail.com> wrote:
>>>> > On Wed, Apr 27, 2016 at 03:24:48PM -0700, H.J. Lu wrote:
>>>> >> bfd_elf_record_link_assignment
>>>> >> is called after check_relocs. bfd_elf_record_link_assignment sets non_elf,
>>>> >> def_regular and forced_local. For PROVIDE, it also updates root.type. They
>>>> >> are needed in reloc_checks.
>>>> >
>>>> > My guess is that symbol twiddling done in before_allocation should be
>>>> > moved to a new ldemul hook called at the start of lang_do_assignments.
>>>> > The idea being to stabilize symbols earlier.
>>>> >
>>>> > The hook would twiddle __ehdr_start and call find_statement_assignment
>>>> > when lang_mark_phase_enum. Reversing the __ehdr_start twiddle stays
>>>> > in before_allocation.
>>>> >
>>>>
>>>> I tried this. But it doesn't work with __start/__stop symbols. I
>>>> need to know if they are defined and referenced local in check_relocs.
>>> [snip]
>>>
>>>> --- a/ld/ldlang.c
>>>> +++ b/ld/ldlang.c
>>>> @@ -6930,6 +6930,8 @@ lang_process (void)
>>>> collection in order to make sure that all symbol aliases are resolved. */
>>>> lang_do_assignments (lang_mark_phase_enum);
>>>>
>>>> + ldemul_record_link_assignments (lang_mark_phase_enum);
>>>> +
>>>> lang_do_memory_regions();
>>>> expld.phase = lang_first_phase_enum;
>>>
>>> You'll need to run ldemul_record_link_assignments before
>>> lang_do_assignments if you want provided symbols to be defined.
>>
>> I got many more failures when I did that since many assignments
>> haven't been processed yet.
>>
>>> I suggest renaming to ldemul_do_assignments and putting
>>> ldemul_do_assignments (phase);
>>> inside lang_do_assignments just before the call to
>>> lang_do_assignments_1.
>>>
>
> With this patch, I only got 2 failures on x86-64.
>
This one works for both i386 and x86-64.
--
H.J.
From b6809eeed88f48dcbe71c1e4ce1213748b0bfe22 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 28 Apr 2016 06:38:41 -0700
Subject: [PATCH] Add _bfd_elf_record_start_stop
---
bfd/elf-bfd.h | 3 ++
bfd/elflink.c | 87 ++++++++++++++++++++++++++++++++++++++++-----------
ld/emultempl/elf32.em | 4 +++
3 files changed, 75 insertions(+), 19 deletions(-)
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 6c05b55..49dc70b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2339,6 +2339,9 @@ extern bfd_boolean bfd_elf_gc_common_final_link
extern asection *_bfd_elf_is_start_stop
(const struct bfd_link_info *, struct elf_link_hash_entry *);
+extern void _bfd_elf_record_start_stop
+ (struct bfd_link_info *);
+
extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
(bfd_vma, void *);
diff --git a/bfd/elflink.c b/bfd/elflink.c
index b6ff6b6..9395052 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12230,8 +12230,9 @@ _bfd_elf_gc_mark_hook (asection *sec,
return NULL;
}
-/* For undefined __start_<name> and __stop_<name> symbols, return the
- first input section matching <name>. Return NULL otherwise. */
+/* For __start_<name> and __stop_<name> symbols, return the first
+ input section matching <name> in a regular object. Return NULL
+ otherwise. */
asection *
_bfd_elf_is_start_stop (const struct bfd_link_info *info,
@@ -12239,17 +12240,28 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info,
{
asection *s;
const char *sec_name;
+ bfd_boolean undefined = (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak);
- if (h->root.type != bfd_link_hash_undefined
- && h->root.type != bfd_link_hash_undefweak)
- return NULL;
-
- s = h->root.u.undef.section;
- if (s != NULL)
+ if (undefined)
+ {
+ s = h->root.u.undef.section;
+ if (s != NULL)
+ {
+ if (s == (asection *) 0 - 1)
+ return NULL;
+ return s;
+ }
+ }
+ else
{
- if (s == (asection *) 0 - 1)
+ /* Symbol is defined. Check if it is also defined in a regular
+ input file only when it is currently defined in a dynamic
+ object, since otherwise, it can't be a __start_<name> nor
+ __stop_<name> symbol. */
+ if (!h->def_dynamic)
return NULL;
- return s;
+ s = NULL;
}
sec_name = NULL;
@@ -12262,18 +12274,21 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info,
{
bfd *i;
+ /* Only check regular input files. */
for (i = info->input_bfds; i != NULL; i = i->link.next)
- {
- s = bfd_get_section_by_name (i, sec_name);
- if (s != NULL)
- {
- h->root.u.undef.section = s;
- break;
- }
- }
+ if ((i->flags
+ & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+ {
+ s = bfd_get_section_by_name (i, sec_name);
+ if (s != NULL)
+ {
+ h->root.u.undef.section = s;
+ break;
+ }
+ }
}
- if (s == NULL)
+ if (undefined && s == NULL)
h->root.u.undef.section = (asection *) 0 - 1;
return s;
@@ -13791,3 +13806,37 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
bed->s->swap_reloc_out (abfd, rel, loc);
}
+
+/* Record __start_<name> and __stop_<name> symbols referenced by
+ regular objects. This is called via elf_link_hash_traverse. */
+
+static bfd_boolean
+elf_link_record_start_stop (struct elf_link_hash_entry *h, void *data)
+{
+ if (!h->def_regular && h->ref_regular)
+ {
+ asection *sec
+ = _bfd_elf_is_start_stop ((struct bfd_link_info *) data, h);
+ if (sec != NULL)
+ {
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+ /* If it is currently defined by a dynamic object, but not
+ by a regular object, then mark it as undefined so that
+ the generic linker will force the correct value. */
+ if (h->def_dynamic)
+ h->root.type = bfd_link_hash_undefined;
+ }
+ }
+ return TRUE;
+}
+
+/* Record all __start_<name> and __stop_<name> symbols referenced by
+ regular objects. */
+
+void
+_bfd_elf_record_start_stop (struct bfd_link_info * info)
+{
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_record_start_stop, info);
+}
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index cc2f056..86105fe 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1445,6 +1445,10 @@ gld${EMULATION_NAME}_record_link_assignments (lang_phase_type phase)
let the ELF backend know about them in case the variables are
referred to by dynamic objects. */
lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+
+ /* Also let the ELF backend know about __start_<name> and
+ __stop_<name> symbols. */
+ _bfd_elf_record_start_stop (&link_info);
}
}
--
2.5.5