public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: "H.J. Lu" <hjl.tools@gmail.com>
To: Alan Modra <amodra@gmail.com>
Cc: Binutils <binutils@sourceware.org>
Subject: Re: PowerPC64 DT_RELR
Date: Mon, 17 Jan 2022 17:08:12 -0800	[thread overview]
Message-ID: <CAMe9rOpBj2LZgPMB0LJ7HXUHpw2SaExVxb62A4ixE8WcAsmrqw@mail.gmail.com> (raw)
In-Reply-To: <YeYPcX41MH1+J3zr@squeak.grove.modra.org>

On Mon, Jan 17, 2022 at 4:54 PM Alan Modra via Binutils
<binutils@sourceware.org> wrote:
>
> PowerPC64 takes a more traditional approach to DT_RELR than x86.  Count
> relative relocs in check_relocs, allocate space for them and output in
> the usual places but not doing so when enable_dt_relr.  DT_RELR is
> sized in the existing ppc stub relaxation machinery, run via the
> linker's ldemul_after_allocation hook.  DT_RELR is output in the same
> function that writes ppc stubs, run via ldemul_finish.
>
> This support should be considered experimental.
>
> bfd/
>         * elf64-ppc.c (struct ppc_local_dyn_relocs): Renamed from
>         ppc_dyn_relocs.  Add rel_count field.  Update uses.
>         (struct ppc_dyn_relocs): New.  Replace all uses of elf_dyn_relocs.
>         (struct ppc_link_hash_table): Add relr_alloc, relr_count and
>         relr_addr.
>         (ppc64_elf_copy_indirect_symbol): Merge rel_count.
>         (ppc64_elf_check_relocs): Init rel_count for global and local syms.
>         (dec_dynrel_count): Change r_info param to reloc pointer.  Update
>         all callers.  Handle decrementing rel_count.
>         (allocate_got): Don't allocate space for relative relocs when
>         enable_dt_relr.
>         (allocate_dynrelocs): Likewise.
>         (ppc64_elf_size_dynamic_sections): Likewise.  Handle srelrdyn.
>         (ppc_build_one_stub): Don't emit relative relocs on .branch_lt.
>         (compare_relr_address, append_relr_off): New functions.
>         (got_and_plt_relr_for_local_syms, got_and_plt_relr): Likewise.
>         (ppc64_elf_size_stubs): Size .relr.syn.
>         (ppc64_elf_build_stubs): Emit .relr.dyn.
>         (build_global_entry_stubs_and_plt): Don't output relative relocs
>         when enable_dt_relr.
>         (write_plt_relocs_for_local_syms): Likewise.
>         (ppc64_elf_relocate_section): Likewise.
> binutils/
>         * testsuite/lib/binutils-common.exp (supports_dt_relr): Add
>         powerpc64.
> ld/
>         * emulparams/elf64ppc.sh: Source dt-relr.sh.
>         * testsuite/ld-elf/dt-relr-2b.d: Adjust for powerpc.
>         * testsuite/ld-elf/dt-relr-2c.d: Likewise.
>         * testsuite/ld-elf/dt-relr-2d.d: Likewise.
>         * testsuite/ld-elf/dt-relr-2e.d: Likewise.
>
> diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
> index ea9e60217bc..0f945797b49 100644
> --- a/bfd/elf64-ppc.c
> +++ b/bfd/elf64-ppc.c
> @@ -3094,7 +3094,7 @@ struct ppc_branch_hash_entry
>    unsigned int iter;
>  };
>
> -/* Used to track dynamic relocations for local symbols.  */
> +/* Used to track dynamic relocations.  */
>  struct ppc_dyn_relocs
>  {
>    struct ppc_dyn_relocs *next;
> @@ -3103,7 +3103,27 @@ struct ppc_dyn_relocs
>    asection *sec;
>
>    /* Total number of relocs copied for the input section.  */
> -  unsigned int count : 31;
> +  unsigned int count;
> +
> +  /* Number of pc-relative relocs copied for the input section.  */
> +  unsigned int pc_count;
> +
> +  /* Number of relocs that might become R_PPC64_RELATIVE.  */
> +  unsigned int rel_count;
> +};
> +
> +struct ppc_local_dyn_relocs
> +{
> +  struct ppc_local_dyn_relocs *next;
> +
> +  /* The input section of the reloc.  */
> +  asection *sec;
> +
> +  /* Total number of relocs copied for the input section.  */
> +  unsigned int count;
> +
> +  /* Number of relocs that might become R_PPC64_RELATIVE.  */
> +  unsigned int rel_count : 31;
>
>    /* Whether this entry is for STT_GNU_IFUNC symbols.  */
>    unsigned int ifunc : 1;
> @@ -3250,6 +3270,11 @@ struct ppc_link_hash_table
>    /* The size of reliplt used by got entry relocs.  */
>    bfd_size_type got_reli_size;
>
> +  /* DT_RELR array of r_offset.  */
> +  size_t relr_alloc;
> +  size_t relr_count;
> +  bfd_vma *relr_addr;
> +
>    /* Statistics.  */
>    unsigned long stub_count[ppc_stub_save_res];
>
> @@ -4068,27 +4093,32 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
>      {
>        if (dir->dyn_relocs != NULL)
>         {
> -         struct elf_dyn_relocs **pp;
> -         struct elf_dyn_relocs *p;
> +         struct ppc_dyn_relocs **pp;
> +         struct ppc_dyn_relocs *p;
>
>           /* Add reloc counts against the indirect sym to the direct sym
>              list.  Merge any entries against the same section.  */
> -         for (pp = &ind->dyn_relocs; (p = *pp) != NULL; )
> +         for (pp = (struct ppc_dyn_relocs **) &ind->dyn_relocs;
> +              (p = *pp) != NULL;
> +              )
>             {
> -             struct elf_dyn_relocs *q;
> +             struct ppc_dyn_relocs *q;
>
> -             for (q = dir->dyn_relocs; q != NULL; q = q->next)
> +             for (q = (struct ppc_dyn_relocs *) dir->dyn_relocs;
> +                  q != NULL;
> +                  q = q->next)
>                 if (q->sec == p->sec)
>                   {
> -                   q->pc_count += p->pc_count;
>                     q->count += p->count;
> +                   q->pc_count += p->pc_count;
> +                   q->rel_count += p->rel_count;
>                     *pp = p->next;
>                     break;
>                   }
>               if (q == NULL)
>                 pp = &p->next;
>             }
> -         *pp = dir->dyn_relocs;
> +         *pp = (struct ppc_dyn_relocs *) dir->dyn_relocs;
>         }
>
>        dir->dyn_relocs = ind->dyn_relocs;
> @@ -5337,10 +5367,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>                  relocations we need for this symbol.  */
>               if (h != NULL)
>                 {
> -                 struct elf_dyn_relocs *p;
> -                 struct elf_dyn_relocs **head;
> +                 struct ppc_dyn_relocs *p;
> +                 struct ppc_dyn_relocs **head;
>
> -                 head = &h->dyn_relocs;
> +                 head = (struct ppc_dyn_relocs **) &h->dyn_relocs;
>                   p = *head;
>                   if (p == NULL || p->sec != sec)
>                     {
> @@ -5352,18 +5382,25 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>                       p->sec = sec;
>                       p->count = 0;
>                       p->pc_count = 0;
> +                     p->rel_count = 0;
>                     }
>                   p->count += 1;
>                   if (!must_be_dyn_reloc (info, r_type))
>                     p->pc_count += 1;
> +                 if ((r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
> +                     && rel->r_offset % 2 == 0
> +                     && sec->alignment_power != 0
> +                     && ((!NO_OPD_RELOCS && is_opd)
> +                         || (!ifunc && SYMBOL_REFERENCES_LOCAL (info, h))))
> +                   p->rel_count += 1;
>                 }
>               else
>                 {
>                   /* Track dynamic relocs needed for local syms too.
>                      We really need local syms available to do this
>                      easily.  Oh well.  */
> -                 struct ppc_dyn_relocs *p;
> -                 struct ppc_dyn_relocs **head;
> +                 struct ppc_local_dyn_relocs *p;
> +                 struct ppc_local_dyn_relocs **head;
>                   bool is_ifunc;
>                   asection *s;
>                   void *vpp;
> @@ -5379,7 +5416,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>                     s = sec;
>
>                   vpp = &elf_section_data (s)->local_dynrel;
> -                 head = (struct ppc_dyn_relocs **) vpp;
> +                 head = (struct ppc_local_dyn_relocs **) vpp;
>                   is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
>                   p = *head;
>                   if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
> @@ -5392,10 +5429,16 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>                       p->next = *head;
>                       *head = p;
>                       p->sec = sec;
> -                     p->ifunc = is_ifunc;
>                       p->count = 0;
> +                     p->rel_count = 0;
> +                     p->ifunc = is_ifunc;
>                     }
>                   p->count += 1;
> +                 if ((r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
> +                     && rel->r_offset % 2 == 0
> +                     && sec->alignment_power != 0
> +                     && ((!NO_OPD_RELOCS && is_opd) || !is_ifunc))
> +                   p->rel_count += 1;
>                 }
>             }
>           break;
> @@ -6576,9 +6619,9 @@ alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
>  static bool
>  pc_dynrelocs (struct ppc_link_hash_entry *eh)
>  {
> -  struct elf_dyn_relocs *p;
> +  struct ppc_dyn_relocs *p;
>
> -  for (p = eh->elf.dyn_relocs; p != NULL; p = p->next)
> +  for (p = (struct ppc_dyn_relocs *) eh->elf.dyn_relocs; p != NULL; p = p->next)
>      if (p->pc_count != 0)
>        return true;
>    return false;
> @@ -7113,7 +7156,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
>     have already been determined.  */
>
>  static bool
> -dec_dynrel_count (bfd_vma r_info,
> +dec_dynrel_count (const Elf_Internal_Rela *rel,
>                   asection *sec,
>                   struct bfd_link_info *info,
>                   Elf_Internal_Sym **local_syms,
> @@ -7125,7 +7168,7 @@ dec_dynrel_count (bfd_vma r_info,
>
>    /* Can this reloc be dynamic?  This switch, and later tests here
>       should be kept in sync with the code in check_relocs.  */
> -  r_type = ELF64_R_TYPE (r_info);
> +  r_type = ELF64_R_TYPE (rel->r_info);
>    switch (r_type)
>      {
>      default:
> @@ -7199,7 +7242,7 @@ dec_dynrel_count (bfd_vma r_info,
>        unsigned long r_symndx;
>        bfd *ibfd = sec->owner;
>
> -      r_symndx = ELF64_R_SYM (r_info);
> +      r_symndx = ELF64_R_SYM (rel->r_info);
>        if (!get_sym_h (&h, &sym, &sym_sec, NULL, local_syms, r_symndx, ibfd))
>         return false;
>      }
> @@ -7222,9 +7265,9 @@ dec_dynrel_count (bfd_vma r_info,
>
>    if (h != NULL)
>      {
> -      struct elf_dyn_relocs *p;
> -      struct elf_dyn_relocs **pp;
> -      pp = &h->dyn_relocs;
> +      struct ppc_dyn_relocs *p;
> +      struct ppc_dyn_relocs **pp;
> +      pp = (struct ppc_dyn_relocs **) &h->dyn_relocs;
>
>        /* elf_gc_sweep may have already removed all dyn relocs associated
>          with local syms for a given section.  Also, symbol flags are
> @@ -7239,6 +7282,14 @@ dec_dynrel_count (bfd_vma r_info,
>             {
>               if (!must_be_dyn_reloc (info, r_type))
>                 p->pc_count -= 1;
> +             if ((r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
> +                 && rel->r_offset % 2 == 0
> +                 && sec->alignment_power != 0
> +                 && ((!NO_OPD_RELOCS
> +                      && ppc64_elf_section_data (sec)->sec_type == sec_opd)
> +                     || (h->type != STT_GNU_IFUNC
> +                         && SYMBOL_REFERENCES_LOCAL (info, h))))
> +               p->rel_count -= 1;
>               p->count -= 1;
>               if (p->count == 0)
>                 *pp = p->next;
> @@ -7249,8 +7300,8 @@ dec_dynrel_count (bfd_vma r_info,
>      }
>    else
>      {
> -      struct ppc_dyn_relocs *p;
> -      struct ppc_dyn_relocs **pp;
> +      struct ppc_local_dyn_relocs *p;
> +      struct ppc_local_dyn_relocs **pp;
>        void *vpp;
>        bool is_ifunc;
>
> @@ -7260,7 +7311,7 @@ dec_dynrel_count (bfd_vma r_info,
>         sym_sec = sec;
>
>        vpp = &elf_section_data (sym_sec)->local_dynrel;
> -      pp = (struct ppc_dyn_relocs **) vpp;
> +      pp = (struct ppc_local_dyn_relocs **) vpp;
>
>        if (*pp == NULL && info->gc_sections)
>         return true;
> @@ -7270,6 +7321,13 @@ dec_dynrel_count (bfd_vma r_info,
>         {
>           if (p->sec == sec && p->ifunc == is_ifunc)
>             {
> +             if ((r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
> +                 && rel->r_offset % 2 == 0
> +                 && sec->alignment_power != 0
> +                 && ((!NO_OPD_RELOCS
> +                      && ppc64_elf_section_data (sec)->sec_type == sec_opd)
> +                     || !is_ifunc))
> +               p->rel_count -= 1;
>               p->count -= 1;
>               if (p->count == 0)
>                 *pp = p->next;
> @@ -7567,7 +7625,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
>                   else
>                     while (1)
>                       {
> -                       if (!dec_dynrel_count (rel->r_info, sec, info,
> +                       if (!dec_dynrel_count (rel, sec, info,
>                                                NULL, h, sym))
>                           goto error_ret;
>
> @@ -8587,13 +8645,13 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
>                     {
>                       /* If we got rid of a DTPMOD/DTPREL reloc pair then
>                          we'll lose one or two dyn relocs.  */
> -                     if (!dec_dynrel_count (rel->r_info, sec, info,
> +                     if (!dec_dynrel_count (rel, sec, info,
>                                              NULL, h, sym))
>                         return false;
>
>                       if (tls_set == (TLS_EXPLICIT | TLS_GD))
>                         {
> -                         if (!dec_dynrel_count ((rel + 1)->r_info, sec, info,
> +                         if (!dec_dynrel_count (rel + 1, sec, info,
>                                                  NULL, h, sym))
>                             return false;
>                         }
> @@ -9419,7 +9477,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
>                     wrel->r_addend = rel->r_addend;
>                     ++wrel;
>                   }
> -               else if (!dec_dynrel_count (rel->r_info, toc, info,
> +               else if (!dec_dynrel_count (rel, toc, info,
>                                             &local_syms, NULL, NULL))
>                   goto error_ret;
>
> @@ -9720,9 +9778,10 @@ allocate_got (struct elf_link_hash_entry *h,
>        htab->got_reli_size += rentsize;
>      }
>    else if (((bfd_link_pic (info)
> -            && !(gent->tls_type != 0
> -                 && bfd_link_executable (info)
> -                 && SYMBOL_REFERENCES_LOCAL (info, h)))
> +            && (gent->tls_type == 0
> +                ? !info->enable_dt_relr
> +                : !(bfd_link_executable (info)
> +                    && SYMBOL_REFERENCES_LOCAL (info, h))))
>             || (htab->elf.dynamic_sections_created
>                 && h->dynindx != -1
>                 && !SYMBOL_REFERENCES_LOCAL (info, h)))
> @@ -9884,7 +9943,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>
>    if (h->dyn_relocs != NULL)
>      {
> -      struct elf_dyn_relocs *p, **pp;
> +      struct ppc_dyn_relocs *p, **pp;
>
>        /* In the shared -Bsymbolic case, discard space allocated for
>          dynamic pc-relative relocs against symbols which turn out to
> @@ -9902,7 +9961,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>              avoid writing weird assembly.  */
>           if (SYMBOL_CALLS_LOCAL (info, h))
>             {
> -             for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
> +             for (pp = (struct ppc_dyn_relocs **) &h->dyn_relocs;
> +                  (p = *pp) != NULL;
> +                  )
>                 {
>                   p->count -= p->pc_count;
>                   p->pc_count = 0;
> @@ -9948,12 +10009,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>         }
>
>        /* Finally, allocate space.  */
> -      for (p = h->dyn_relocs; p != NULL; p = p->next)
> +      for (p = (struct ppc_dyn_relocs *) h->dyn_relocs; p != NULL; p = p->next)
>         {
> +         unsigned int count;
>           asection *sreloc = elf_section_data (p->sec)->sreloc;
>           if (eh->elf.type == STT_GNU_IFUNC)
>             sreloc = htab->elf.irelplt;
> -         sreloc->size += p->count * sizeof (Elf64_External_Rela);
> +         count = p->count;
> +         if (info->enable_dt_relr)
> +           count -= p->rel_count;
> +         sreloc->size += count * sizeof (Elf64_External_Rela);
>         }
>      }
>
> @@ -9994,7 +10059,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>                     s = htab->pltlocal;
>                     pent->plt.offset = s->size;
>                     s->size += LOCAL_PLT_ENTRY_SIZE (htab);
> -                   s = bfd_link_pic (info) ? htab->relpltlocal : NULL;
> +                   s = NULL;
> +                   if (bfd_link_pic (info)
> +                       && !(info->enable_dt_relr && !htab->opd_abi))
> +                     s = htab->relpltlocal;
>                   }
>               }
>             else
> @@ -10180,7 +10248,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
>
>        for (s = ibfd->sections; s != NULL; s = s->next)
>         {
> -         struct ppc_dyn_relocs *p;
> +         struct ppc_local_dyn_relocs *p;
>
>           for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
>             {
> @@ -10194,10 +10262,16 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
>                 }
>               else if (p->count != 0)
>                 {
> -                 asection *srel = elf_section_data (p->sec)->sreloc;
> +                 unsigned int count;
> +                 asection *srel;
> +
> +                 count = p->count;
> +                 if (info->enable_dt_relr)
> +                   count -= p->rel_count;
> +                 srel = elf_section_data (p->sec)->sreloc;
>                   if (p->ifunc)
>                     srel = htab->elf.irelplt;
> -                 srel->size += p->count * sizeof (Elf64_External_Rela);
> +                 srel->size += count * sizeof (Elf64_External_Rela);
>                   if ((p->sec->output_section->flags & SEC_READONLY) != 0)
>                     info->flags |= DF_TEXTREL;
>                 }
> @@ -10342,7 +10416,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
>        if ((s->flags & SEC_LINKER_CREATED) == 0)
>         continue;
>
> -      if (s == htab->brlt || s == htab->relbrlt)
> +      if (s == htab->brlt || s == htab->relbrlt || s == htab->elf.srelrdyn)
>         /* These haven't been allocated yet;  don't strip.  */
>         continue;
>        else if (s == htab->elf.sgot
> @@ -11693,7 +11767,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
>         {
>           br_entry->iter = 0;
>
> -         if (htab->relbrlt != NULL)
> +         if (htab->relbrlt != NULL && !info->enable_dt_relr)
>             {
>               /* Create a reloc for the branch lookup table entry.  */
>               Elf_Internal_Rela rela;
> @@ -12198,7 +12272,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
>               br_entry->offset = htab->brlt->size;
>               htab->brlt->size += 8;
>
> -             if (htab->relbrlt != NULL)
> +             if (htab->relbrlt != NULL && !info->enable_dt_relr)
>                 htab->relbrlt->size += sizeof (Elf64_External_Rela);
>               else if (info->emitrelocations)
>                 {
> @@ -13293,6 +13367,174 @@ maybe_strip_output (struct bfd_link_info *info, asection *isec)
>      }
>  }
>
> +static int
> +compare_relr_address (const void *arg1, const void *arg2)
> +{
> +  bfd_vma a = *(bfd_vma *) arg1;
> +  bfd_vma b = *(bfd_vma *) arg2;
> +  return a < b ? -1 : a > b ? 1 : 0;
> +}
> +
> +static bool
> +append_relr_off (struct ppc_link_hash_table *htab, bfd_vma off)
> +{
> +  if (htab->relr_count >= htab->relr_alloc)
> +    {
> +      if (htab->relr_alloc == 0)
> +       htab->relr_alloc = 4096;
> +      else
> +       htab->relr_alloc *= 2;
> +      htab->relr_addr
> +       = bfd_realloc (htab->relr_addr,
> +                      htab->relr_alloc * sizeof (htab->relr_addr[0]));
> +      if (htab->relr_addr == NULL)
> +       return false;
> +    }
> +  htab->relr_addr[htab->relr_count++] = off;
> +  return true;
> +}
> +
> +static bool
> +got_and_plt_relr_for_local_syms (struct bfd_link_info *info)
> +{
> +  struct ppc_link_hash_table *htab = ppc_hash_table (info);
> +  bfd *ibfd;
> +
> +  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
> +    {
> +      struct got_entry **lgot_ents, **lgot, **end_lgot_ents;
> +      struct plt_entry **local_plt, **lplt, **end_local_plt;
> +      Elf_Internal_Shdr *symtab_hdr;
> +      bfd_size_type locsymcount;
> +      Elf_Internal_Sym *local_syms = NULL;
> +      struct plt_entry *pent;
> +      struct got_entry *gent;
> +
> +      if (!is_ppc64_elf (ibfd))
> +       continue;
> +
> +      lgot_ents = elf_local_got_ents (ibfd);
> +      if (!lgot_ents)
> +       continue;
> +
> +      symtab_hdr = &elf_symtab_hdr (ibfd);
> +      locsymcount = symtab_hdr->sh_info;
> +      end_lgot_ents = lgot_ents + locsymcount;
> +      local_plt = (struct plt_entry **) end_lgot_ents;
> +      end_local_plt = local_plt + locsymcount;
> +      for (lgot = lgot_ents; lgot < end_lgot_ents; ++lgot)
> +       for (gent = *lgot; gent != NULL; gent = gent->next)
> +         if (!gent->is_indirect
> +             && gent->tls_type == 0
> +             && gent->got.offset != (bfd_vma) -1)
> +           {
> +             asection *got = ppc64_elf_tdata (gent->owner)->got;
> +             bfd_vma r_offset = (got->output_section->vma
> +                                 + got->output_offset
> +                                 + gent->got.offset);
> +             if (!append_relr_off (htab, r_offset))
> +               {
> +                 htab->stub_error = true;
> +                 return false;
> +               }
> +           }
> +
> +      if (!htab->opd_abi)
> +       for (lplt = local_plt; lplt < end_local_plt; ++lplt)
> +         for (pent = *lplt; pent != NULL; pent = pent->next)
> +           if (pent->plt.offset != (bfd_vma) -1)
> +             {
> +               Elf_Internal_Sym *sym;
> +
> +               if (!get_sym_h (NULL, &sym, NULL, NULL, &local_syms,
> +                               lplt - local_plt, ibfd))
> +                 {
> +                 err_exit:
> +                   if (symtab_hdr->contents != (unsigned char *) local_syms)
> +                     free (local_syms);
> +                   return false;
> +                 }
> +
> +               if (ELF_ST_TYPE (sym->st_info) != STT_GNU_IFUNC)
> +                 {
> +                   bfd_vma r_offset = (pent->plt.offset
> +                                       + htab->pltlocal->output_offset
> +                                       + htab->pltlocal->output_section->vma);
> +                   if (!append_relr_off (htab, r_offset))
> +                     goto err_exit;
> +                 }
> +             }
> +
> +      if (local_syms != NULL
> +         && symtab_hdr->contents != (unsigned char *) local_syms)
> +       {
> +         if (!info->keep_memory)
> +           free (local_syms);
> +         else
> +           symtab_hdr->contents = (unsigned char *) local_syms;
> +       }
> +    }
> +  return true;
> +}
> +
> +static bool
> +got_and_plt_relr (struct elf_link_hash_entry *h, void *inf)
> +{
> +  struct bfd_link_info *info;
> +  struct ppc_link_hash_table *htab;
> +  struct plt_entry *pent;
> +  struct got_entry *gent;
> +
> +  if (h->root.type == bfd_link_hash_indirect)
> +    return true;
> +
> +  info = (struct bfd_link_info *) inf;
> +  htab = ppc_hash_table (info);
> +  if (htab == NULL)
> +    return false;
> +
> +  if (h->type != STT_GNU_IFUNC
> +      && h->def_regular
> +      && (h->root.type == bfd_link_hash_defined
> +         || h->root.type == bfd_link_hash_defweak))
> +    {
> +      if (!htab->elf.dynamic_sections_created
> +         || h->dynindx == -1
> +         || SYMBOL_REFERENCES_LOCAL (info, h))
> +       for (gent = h->got.glist; gent != NULL; gent = gent->next)
> +         if (!gent->is_indirect
> +             && gent->tls_type == 0
> +             && gent->got.offset != (bfd_vma) -1)
> +           {
> +             asection *got = ppc64_elf_tdata (gent->owner)->got;
> +             bfd_vma r_offset = (got->output_section->vma
> +                                 + got->output_offset
> +                                 + gent->got.offset);
> +             if (!append_relr_off (htab, r_offset))
> +               {
> +                 htab->stub_error = true;
> +                 return false;
> +               }
> +           }
> +
> +      if (!htab->opd_abi
> +         && use_local_plt (info, h))
> +       for (pent = h->plt.plist; pent != NULL; pent = pent->next)
> +         if (pent->plt.offset != (bfd_vma) -1)
> +           {
> +             bfd_vma r_offset = (htab->pltlocal->output_section->vma
> +                                 + htab->pltlocal->output_offset
> +                                 + pent->plt.offset);
> +             if (!append_relr_off (htab, r_offset))
> +               {
> +                 htab->stub_error = true;
> +                 return false;
> +               }
> +           }
> +    }
> +  return true;
> +}
> +
>  /* Determine and set the size of the stub section for a final link.
>
>     The basic idea here is to examine all the relocations looking for
> @@ -13413,6 +13655,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>        struct map_stub *group;
>
>        htab->stub_iteration += 1;
> +      htab->relr_count = 0;
>
>        for (input_bfd = info->input_bfds, bfd_indx = 0;
>            input_bfd != NULL;
> @@ -13436,16 +13679,20 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>                section = section->next)
>             {
>               Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
> +             bool is_opd;
>
>               /* If there aren't any relocs, then there's nothing more
>                  to do.  */
>               if ((section->flags & SEC_RELOC) == 0
>                   || (section->flags & SEC_ALLOC) == 0
>                   || (section->flags & SEC_LOAD) == 0
> -                 || (section->flags & SEC_CODE) == 0
>                   || section->reloc_count == 0)
>                 continue;
>
> +             if (!info->enable_dt_relr
> +                 && (section->flags & SEC_CODE) == 0)
> +               continue;
> +
>               /* If this section is a link-once section that will be
>                  discarded, then don't create any stubs.  */
>               if (section->output_section == NULL
> @@ -13459,6 +13706,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>               if (internal_relocs == NULL)
>                 goto error_ret_free_local;
>
> +             is_opd = ppc64_elf_section_data (section)->sec_type == sec_opd;
> +
>               /* Now examine each relocation.  */
>               irela = internal_relocs;
>               irelaend = irela + section->reloc_count;
> @@ -13492,21 +13741,76 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>                     }
>
>                   /* Only look for stubs on branch instructions.  */
> -                 if (r_type != R_PPC64_REL24
> -                     && r_type != R_PPC64_REL24_NOTOC
> -                     && r_type != R_PPC64_REL24_P9NOTOC
> -                     && r_type != R_PPC64_REL14
> -                     && r_type != R_PPC64_REL14_BRTAKEN
> -                     && r_type != R_PPC64_REL14_BRNTAKEN)
> -                   continue;
> +                 switch (r_type)
> +                   {
> +                   default:
> +                     continue;
> +
> +                   case R_PPC64_REL24:
> +                   case R_PPC64_REL24_NOTOC:
> +                   case R_PPC64_REL24_P9NOTOC:
> +                   case R_PPC64_REL14:
> +                   case R_PPC64_REL14_BRTAKEN:
> +                   case R_PPC64_REL14_BRNTAKEN:
> +                     if ((section->flags & SEC_CODE) != 0)
> +                       break;
> +                     continue;
> +
> +                   case R_PPC64_ADDR64:
> +                   case R_PPC64_TOC:
> +                     if (info->enable_dt_relr
> +                         && irela->r_offset % 2 == 0
> +                         && section->alignment_power != 0)
> +                       break;
> +                     continue;
> +                   }
>
>                   /* Now determine the call target, its name, value,
>                      section.  */
>                   if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
>                                   r_indx, input_bfd))
>                     goto error_ret_free_internal;
> -                 hash = ppc_elf_hash_entry (h);
>
> +                 if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
> +                   {
> +                     /* Only locally defined symbols can possibly use
> +                        relative relocations.  */
> +                     bfd_vma r_offset;
> +                     if ((sym_sec == NULL
> +                          || sym_sec->output_section == NULL)
> +                         /* No symbol is OK too.  */
> +                         && !(sym != NULL && sym->st_shndx == 0)
> +                         /* Hack for __ehdr_start, which is undefined
> +                            at this point.  */
> +                         && !(h != NULL && h->root.linker_def))
> +                       continue;
> +                     if (NO_OPD_RELOCS && is_opd)
> +                       continue;
> +                     if (!is_opd
> +                         && r_type == R_PPC64_ADDR64)
> +                       {
> +                         if (h != NULL
> +                             ? h->type == STT_GNU_IFUNC
> +                             : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
> +                           continue;
> +                         if (h != NULL
> +                             && !SYMBOL_REFERENCES_LOCAL (info, h))
> +                           continue;
> +                       }
> +                     r_offset = _bfd_elf_section_offset (info->output_bfd,
> +                                                         info,
> +                                                         section,
> +                                                         irela->r_offset);
> +                     if (r_offset >= (bfd_vma) -2)
> +                       continue;
> +                     r_offset += (section->output_section->vma
> +                                  + section->output_offset);
> +                     if (!append_relr_off (htab, r_offset))
> +                       goto error_ret_free_internal;
> +                     continue;
> +                   }
> +
> +                 hash = ppc_elf_hash_entry (h);
>                   ok_dest = false;
>                   fdh = NULL;
>                   sym_value = 0;
> @@ -13804,6 +14108,14 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>        if (htab->relbrlt != NULL)
>         htab->relbrlt->size = 0;
>
> +      if (htab->elf.srelrdyn != NULL)
> +       {
> +         if (htab->stub_iteration <= STUB_SHRINK_ITER
> +             || htab->elf.srelrdyn->rawsize < htab->elf.srelrdyn->size)
> +           htab->elf.srelrdyn->rawsize = htab->elf.srelrdyn->size;
> +         htab->elf.srelrdyn->size = 0;
> +       }
> +
>        bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
>
>        for (group = htab->group; group != NULL; group = group->next)
> @@ -13845,6 +14157,53 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>                 = (group->stub_sec->size + (1 << align) - 1) & -(1 << align);
>             }
>
> +      if (htab->elf.srelrdyn != NULL)
> +       {
> +         bfd_vma r_offset;
> +
> +         for (r_offset = 0; r_offset < htab->brlt->size; r_offset += 8)
> +           if (!append_relr_off (htab, (r_offset
> +                                        + htab->brlt->output_section->vma
> +                                        + htab->brlt->output_offset)))
> +             return false;
> +
> +         if (!got_and_plt_relr_for_local_syms (info))
> +           return false;
> +         elf_link_hash_traverse (&htab->elf, got_and_plt_relr, info);
> +         if (htab->stub_error)
> +           return false;
> +
> +         if (htab->relr_count > 1)
> +           qsort (htab->relr_addr, htab->relr_count, sizeof (*htab->relr_addr),
> +                  compare_relr_address);
> +
> +         size_t i = 0;
> +         while (i < htab->relr_count)
> +           {
> +             bfd_vma base = htab->relr_addr[i];
> +             htab->elf.srelrdyn->size += 8;
> +             i++;
> +             /* Handle possible duplicate address.  This can happen
> +                as sections increase in size when adding stubs.  */
> +             while (i < htab->relr_count
> +                    && htab->relr_addr[i] == base)
> +               i++;
> +             base += 8;
> +             while (1)
> +               {
> +                 size_t start_i = i;
> +                 while (i < htab->relr_count
> +                        && htab->relr_addr[i] - base < 63 * 8
> +                        && (htab->relr_addr[i] - base) % 8 == 0)
> +                   i++;
> +                 if (i == start_i)
> +                   break;
> +                 htab->elf.srelrdyn->size += 8;
> +                 base += 63 * 8;
> +               }
> +           }
> +       }
> +
>        for (group = htab->group; group != NULL; group = group->next)
>         if (group->stub_sec != NULL
>             && group->stub_sec->rawsize != group->stub_sec->size
> @@ -13856,6 +14215,10 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>           && (htab->brlt->rawsize == htab->brlt->size
>               || (htab->stub_iteration > STUB_SHRINK_ITER
>                   && htab->brlt->rawsize > htab->brlt->size))
> +         && (htab->elf.srelrdyn == NULL
> +             || htab->elf.srelrdyn->rawsize == htab->elf.srelrdyn->size
> +             || (htab->stub_iteration > STUB_SHRINK_ITER
> +                 && htab->elf.srelrdyn->rawsize > htab->elf.srelrdyn->size))
>           && (htab->glink_eh_frame == NULL
>               || htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size)
>           && (htab->tga_group == NULL
> @@ -13959,6 +14322,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
>      maybe_strip_output (info, htab->relbrlt);
>    if (htab->glink_eh_frame != NULL)
>      maybe_strip_output (info, htab->glink_eh_frame);
> +  if (htab->elf.srelrdyn != NULL)
> +    maybe_strip_output (info, htab->elf.srelrdyn);
>
>    return true;
>  }
> @@ -14120,7 +14485,9 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
>             else
>               {
>                 plt = htab->pltlocal;
> -               if (bfd_link_pic (info))
> +               relplt = NULL;
> +               if (bfd_link_pic (info)
> +                   && !(info->enable_dt_relr && !htab->opd_abi))
>                   {
>                     relplt = htab->relpltlocal;
>                     if (htab->opd_abi)
> @@ -14128,8 +14495,6 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
>                     else
>                       rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
>                   }
> -               else
> -                 relplt = NULL;
>               }
>             rela.r_addend = defined_sym_val (h) + ent->addend;
>
> @@ -14311,7 +14676,10 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
>               else
>                 {
>                   plt = htab->pltlocal;
> -                 relplt = bfd_link_pic (info) ? htab->relpltlocal : NULL;
> +                 relplt = NULL;
> +                 if (bfd_link_pic (info)
> +                     && !(info->enable_dt_relr && !htab->opd_abi))
> +                   relplt = htab->relpltlocal;
>                 }
>
>               if (relplt == NULL)
> @@ -14749,6 +15117,55 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
>         }
>      }
>
> +  if (htab->elf.srelrdyn != NULL && htab->elf.srelrdyn->size != 0)
> +    {
> +      htab->elf.srelrdyn->contents
> +       = bfd_alloc (htab->elf.dynobj, htab->elf.srelrdyn->size);
> +      if (htab->elf.srelrdyn->contents == NULL)
> +       return false;
> +
> +      size_t i = 0;
> +      bfd_byte *loc = htab->elf.srelrdyn->contents;
> +      while (i < htab->relr_count)
> +       {
> +         bfd_vma base = htab->relr_addr[i];
> +         BFD_ASSERT (base % 2 == 0);
> +         bfd_put_64 (htab->elf.dynobj, base, loc);
> +         loc += 8;
> +         i++;
> +         while (i < htab->relr_count
> +                && htab->relr_addr[i] == base)
> +           {
> +             htab->stub_error = true;
> +             i++;
> +           }
> +         base += 8;
> +         while (1)
> +           {
> +             bfd_vma bits = 0;
> +             while (i < htab->relr_count
> +                    && htab->relr_addr[i] - base < 63 * 8
> +                    && (htab->relr_addr[i] - base) % 8 == 0)
> +               {
> +                 bits |= (bfd_vma) 1 << ((htab->relr_addr[i] - base) / 8);
> +                 i++;
> +               }
> +             if (bits == 0)
> +               break;
> +             bfd_put_64 (htab->elf.dynobj, (bits << 1) | 1, loc);
> +             loc += 8;
> +             base += 63 * 8;
> +           }
> +       }
> +      /* Pad any excess with 1's, a do-nothing encoding.  */
> +      while ((size_t) (loc - htab->elf.srelrdyn->contents)
> +            < htab->elf.srelrdyn->size)
> +       {
> +         bfd_put_64 (htab->elf.dynobj, 1, loc);
> +         loc += 8;
> +       }
> +    }
> +
>    for (group = htab->group; group != NULL; group = group->next)
>      if ((stub_sec = group->stub_sec) != NULL)
>        {
> @@ -14760,14 +15177,14 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
>        }
>
>    if (group != NULL)
> +    htab->stub_error = true;
> +
> +  if (htab->stub_error)
>      {
> -      htab->stub_error = true;
>        _bfd_error_handler (_("stubs don't match calculated size"));
> +      return false;
>      }
>
> -  if (htab->stub_error)
> -    return false;
> -
>    if (stats != NULL)
>      {
>        char *groupmsg;
> @@ -16462,10 +16879,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
>                               outrel.r_addend -= htab->elf.tls_sec->vma;
>                           }
>                       }
> -                   loc = relgot->contents;
> -                   loc += (relgot->reloc_count++
> -                           * sizeof (Elf64_External_Rela));
> -                   bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
> +                   if (!(info->enable_dt_relr
> +                         && ELF64_R_TYPE (outrel.r_info) == R_PPC64_RELATIVE))
> +                     {
> +                       loc = relgot->contents;
> +                       loc += (relgot->reloc_count++
> +                               * sizeof (Elf64_External_Rela));
> +                       bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
> +                     }
>                   }
>
>                 /* Init the .got section contents here if we're not
> @@ -16924,24 +17345,31 @@ ppc64_elf_relocate_section (bfd *output_bfd,
>                     }
>                 }
>
> -             sreloc = elf_section_data (input_section)->sreloc;
> -             if (h != NULL
> -                 ? h->elf.type == STT_GNU_IFUNC
> -                 : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
> +             if (!(info->enable_dt_relr
> +                   && ELF64_R_TYPE (outrel.r_info) == R_PPC64_RELATIVE
> +                   && rel->r_offset % 2 == 0
> +                   && input_section->alignment_power != 0
> +                   && ELF64_R_TYPE (orig_rel.r_info) != R_PPC64_UADDR64))
>                 {
> -                 sreloc = htab->elf.irelplt;
> -                 if (indx == 0 || is_static_defined (&h->elf))
> -                   htab->elf.ifunc_resolvers = true;
> +                 sreloc = elf_section_data (input_section)->sreloc;
> +                 if (h != NULL
> +                     ? h->elf.type == STT_GNU_IFUNC
> +                     : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
> +                   {
> +                     sreloc = htab->elf.irelplt;
> +                     if (indx == 0 || is_static_defined (&h->elf))
> +                       htab->elf.ifunc_resolvers = true;
> +                   }
> +                 if (sreloc == NULL)
> +                   abort ();
> +
> +                 if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
> +                     >= sreloc->size)
> +                   abort ();
> +                 loc = sreloc->contents;
> +                 loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
> +                 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
>                 }
> -             if (sreloc == NULL)
> -               abort ();
> -
> -             if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
> -                 >= sreloc->size)
> -               abort ();
> -             loc = sreloc->contents;
> -             loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
> -             bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
>
>               if (!warned_dynamic
>                   && !ppc64_glibc_dynamic_reloc (ELF64_R_TYPE (outrel.r_info)))
> diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
> index 93603b0be68..2a2aaf4a17d 100644
> --- a/binutils/testsuite/lib/binutils-common.exp
> +++ b/binutils/testsuite/lib/binutils-common.exp
> @@ -429,7 +429,9 @@ proc supports_persistent_section {} {
>
>  # Whether a target support DT_RELR sections.
>  proc supports_dt_relr {} {
> -    if { ([istarget x86_64-*-*] || [istarget i?86-*-*])
> +    if { ([istarget x86_64-*-*]
> +         || [istarget i?86-*-*]
> +         || [istarget powerpc64*-*-*])
>          && ([istarget *-*-linux*]
>              || [istarget *-*-gnu*]) } {
>         return 1
> diff --git a/ld/emulparams/elf64ppc.sh b/ld/emulparams/elf64ppc.sh
> index 15221b82220..a18393b7202 100644
> --- a/ld/emulparams/elf64ppc.sh
> +++ b/ld/emulparams/elf64ppc.sh
> @@ -1,5 +1,6 @@
>  source_sh ${srcdir}/emulparams/elf32ppccommon.sh
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
> +source_sh ${srcdir}/emulparams/dt-relr.sh
>  EXTRA_EM_FILE=ppc64elf
>  ELFSIZE=64
>  OUTPUT_FORMAT="elf64-powerpc"
> diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
> index cea2931e37d..b1391566a13 100644
> --- a/ld/testsuite/ld-elf/dt-relr-2b.d
> +++ b/ld/testsuite/ld-elf/dt-relr-2b.d
> @@ -10,7 +10,7 @@
>  #...
>  Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
>  #...
> -[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> +[0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
>  #...
>  Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>    4 offsets
> diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
> index 73087a67533..c285e8707d7 100644
> --- a/ld/testsuite/ld-elf/dt-relr-2c.d
> +++ b/ld/testsuite/ld-elf/dt-relr-2c.d
> @@ -10,7 +10,7 @@
>  #...
>  Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>  #...
> -[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> +[0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
>  #...
>  Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>    3 offsets
> diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
> index 4987b0865a3..7fd3046a1cf 100644
> --- a/ld/testsuite/ld-elf/dt-relr-2d.d
> +++ b/ld/testsuite/ld-elf/dt-relr-2d.d
> @@ -10,7 +10,7 @@
>  #...
>  Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
>  #...
> -[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> +[0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
>  #...
>  Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>    4 offsets
> diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
> index 24ce6cc0070..cdff8465a57 100644
> --- a/ld/testsuite/ld-elf/dt-relr-2e.d
> +++ b/ld/testsuite/ld-elf/dt-relr-2e.d
> @@ -10,7 +10,7 @@
>  #...
>  Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 1 entry:
>  #...
> -[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> +[0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
>  #...
>  Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>    4 offsets
>
> --
> Alan Modra
> Australia Development Lab, IBM

You can test your linker wiith the glibc build using users/hjl/relr/master
branch:

https://gitlab.com/x86-glibc/glibc/-/commits/users/hjl/relr/master

by enabling -Wl,-z,pack-relative-relocs by default.

-- 
H.J.

  reply	other threads:[~2022-01-18  1:08 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-18  0:53 Alan Modra
2022-01-18  1:08 ` H.J. Lu [this message]
2022-01-18 13:32   ` H.J. Lu
2022-01-18 23:24     ` Alan Modra
2022-01-19 22:56       ` H.J. Lu
2022-01-22  4:28         ` Alan Modra
2022-01-22 13:04           ` H.J. Lu
2022-01-23 13:51           ` H.J. Lu
2022-03-02  8:41             ` Alan Modra
2022-03-03  2:33               ` PowerPC64 DT_RELR relative reloc addresses Alan Modra
2022-03-09  1:25               ` PowerPC64 DT_RELR Fangrui Song
     [not found]               ` <MWHPR1201MB0110441CD99C43F8215D15EBCB0A9@MWHPR1201MB0110.namprd12.prod.outlook.com>
2022-03-09 21:07                 ` Alan Modra
2022-06-09 10:57 ` Florian Weimer
2022-06-09 22:57   ` Alan Modra
2022-06-09 23:53     ` Alan Modra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMe9rOpBj2LZgPMB0LJ7HXUHpw2SaExVxb62A4ixE8WcAsmrqw@mail.gmail.com \
    --to=hjl.tools@gmail.com \
    --cc=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).