From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by sourceware.org (Postfix) with ESMTPS id 8FEF83857C4D for ; Tue, 18 Jan 2022 13:33:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8FEF83857C4D Received: by mail-pj1-x102b.google.com with SMTP id a1-20020a17090a688100b001b3fd52338eso2814115pjd.1 for ; Tue, 18 Jan 2022 05:33:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=iyGU9hHpXarjTqTX/Z6PUBYMq6obEeeVG4JLbaPMIxM=; b=FUU1NV+l2yhPxVqwtTBbsMiTfnzpNhW0SEk1fpIQZH5XjPynpMS+NycaKw4u7LToMW jHCfFjhNs2UMaisVGtR4mLoTKMDSX7hkSIlch9z5hE4nEzy8Am811eIG9M/ksflAfEBh pxa4tvCz3T3wNHh6swJiGqYyiqXbG/0JWEj3MkoyfZxJnDeMLePa2ZIGNJGNSbCuRadj pkxArtughj1oPWn9pu+LhBjPJPRJMZn+LBGbiTjQjzpw9fmHXQtOjd43cPedOXu9S5QI eRiSa1tJCOIcL0KqtEsKQ3aUnZraUUVjTsP9oDTm8t0q+vaxbyc/zV+g76WoyLitwYQP ISvg== X-Gm-Message-State: AOAM530yEHVp117YxuOxzc7hWOxGHqsfAhJAZyGDfo1RoEtksCX+gknS BfVXTdam1xOzCDoeL2YptWXqsZbVAldI44e8JkNUwOhhaAA= X-Google-Smtp-Source: ABdhPJxl9OucmoFaKgs7wW+Xk62Jl1d3rXvQuJbASR1NQ+vkvI2MJ80M+38d5WM1PhIWlw5Gf9Dp1jSnbRiLqRjjmdA= X-Received: by 2002:a17:90b:1811:: with SMTP id lw17mr13171033pjb.120.1642512794060; Tue, 18 Jan 2022 05:33:14 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: "H.J. Lu" Date: Tue, 18 Jan 2022 05:32:37 -0800 Message-ID: Subject: Re: PowerPC64 DT_RELR To: Alan Modra Cc: Binutils Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-3027.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Jan 2022 13:33:20 -0000 On Mon, Jan 17, 2022 at 5:08 PM H.J. Lu wrote: > > On Mon, Jan 17, 2022 at 4:54 PM Alan Modra via Binutils > 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 s> > @@ -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. > I tried binutils master branch on glibc master branch: $ readelf -r libc.so.6 Relocation section '.rela.dyn' at offset 0x21d38 contains 562 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000000 000000000000 R_PPC64_NONE 0 000000000000 000000000000 R_PPC64_NONE 0 There are 238 R_PPC64_NONEs in libc.so.6 alone. There is none for i686, x32 and x86-64. -- H.J.