Re: Use stub bfd for dynobj
Alan Modra <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Aug 20, 2026 at 11:56:16PM +0930, Alan Modra wrote:
> On Thu, Aug 20, 2026 at 11:49:46AM +0200, Andreas Schwab wrote:
> > You can find /home/schwab/ld-test.tar.xz on cfarm13.cfarm.net which
> > contains the input files and a script to reproduce the issue.
>
> Thanks. It is an ordering problem.
>
> This loop in elflink.c:_bfd_elf_final_link
> for (o = obfd->sections; o != NULL; o = o->next)
> {
> for (p = o->map_head.link_order; p != NULL; p = p->next)
> {
> if (p->type == bfd_indirect_link_order
> && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
> == bfd_target_elf_flavour)
> && elf_elfheader (sub)->e_ident[EI_CLASS] == obed->s->elfclass)
> {
> if (! sub->output_has_begun)
> {
> if (! elf_link_input_bfd (&flinfo, sub))
> goto error_return;
> sub->output_has_begun = true;
> }
> }
> passes the "linker stubs" to elf_link_input_bfd much earlier when
> dynobj is using the stub bfd. That's because .interp is early in the
> output bfd sections and dynobj provides .interp. So the stubs get
> written out early, before _bfd_aarch64_erratum_843419_branch_to_stub
> has a chance to copy the insn to the stub.
>
> Prior to commit e189bfd9b4 the "linker stubs" bfd typically was passed
> to elf_link_input_bfd when the output bfd .text section was reached,
> and that mostly allowed _bfd_aarch64_erratum_843419_branch_to_stub to
> work. It's quite fragile though, and certainly could be broken with
> user linker scripts.
I'm going to commit the following.
Subject: Delay writing of stub bfd sections
AARCH64 continues an ARM tradition of updating stubs late. See
coff_arm_link_output_has_begun. Commit e189bfd9b492 broke AARCH64,
because adding dynamic sections to the stub bfd resulted in that
entire bfd being written out fairly early. Prior to e189bfd9b492
dynamic sections were usually added to crt1.o, the first object being
linked. If crt1.o happened to need an erratum_843419 stub I think
we'd see the same sort of breakage exposed by e189bfd9b492, with later
object files' erratum_843419 stubs not being updated (resulting in
an all-zero insn in the stub). You would likely hit the same problem
if user linker scripts divided up code sections for some reason.
There likely is no reason to clear sub->output_has_begun here, but
I'll leave removing that to a followup patch.
* elflink.c (_bfd_elf_final_link): Write any linker created
bfd sections last.
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d1edf1bddf7..df9c698d874 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -13193,7 +13193,8 @@ _bfd_elf_final_link (bfd *obfd, struct bfd_link_info *info)
{
if (! sub->output_has_begun)
{
- if (! elf_link_input_bfd (&flinfo, sub))
+ if ((sub->flags & BFD_LINKER_CREATED) == 0
+ && !elf_link_input_bfd (&flinfo, sub))
goto error_return;
sub->output_has_begun = true;
}
@@ -13244,6 +13245,17 @@ _bfd_elf_final_link (bfd *obfd, struct bfd_link_info *info)
}
}
}
+ /* Writing of linker created BFDs is left until last, because the
+ aarch64 backend wants to copy insns from a relocated section to
+ a stub section. See erratum_843419 code. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+ if (sub->output_has_begun && (sub->flags & BFD_LINKER_CREATED) != 0)
+ {
+ sub->output_has_begun = false;
+ if (!elf_link_input_bfd (&flinfo, sub))
+ goto error_return;
+ sub->output_has_begun = true;
+ }
/* Free symbol buffer if needed. */
if (!info->reduce_memory_overheads)
--
Alan Modra