From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id 90C133858D39 for ; Thu, 3 Mar 2022 02:33:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 90C133858D39 Received: by mail-pf1-x42c.google.com with SMTP id z15so3574119pfe.7 for ; Wed, 02 Mar 2022 18:33:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=d1W7hxfNf4B6LavgejF20raOyeSONEDQPiEf/JVgoio=; b=SgN2VG4aky1w9+ujppM+2D3EmXvL36YcHoNFR95H6kzLcZvChnjLyJNGODRflFnVx/ ZY+qFi+KRYGWOADik5rBv6I1jr38TGdBz4avWHi8VUv5kfH//b/2W/WzLHDTYoWfZGYf elPrdQfttXOsPEzNQ7tugC6DHwj1/KOMDs2C+StiEjF8kRweSwQtsTPgCTrBv4ksKF+F 2NhjwlVLxphLcsFIxznZu+7cd9L6xDOvlwRrZt9W4SDBOjMJCbsgoIHkgERSdUI7e8YN h97O+EMMsNajqRGInAA/yhD82PyrUhsbLCxJ1ZonJQAhmSOALbaBDCxGpwvKnnv8zD5T +bGw== X-Gm-Message-State: AOAM531Fa0X+Y0gTegS2hU8SNfH3N1Q9n+5xy1+zNxdTwiS5GTAX88FI c6EeyqrsSOUn7NF8yGWM1m+TqIW+zU8= X-Google-Smtp-Source: ABdhPJwvf6mK2a1yy1uaAWIJ86GIhTTD0L642/stQko8R0AH3FJggJR+i9Helvn3UtCEr4XghsHoWA== X-Received: by 2002:a62:8c8f:0:b0:4cf:4c5:b2ad with SMTP id m137-20020a628c8f000000b004cf04c5b2admr36340454pfd.71.1646274824443; Wed, 02 Mar 2022 18:33:44 -0800 (PST) Received: from squeak.grove.modra.org (158.106.96.58.static.exetel.com.au. [58.96.106.158]) by smtp.gmail.com with ESMTPSA id on18-20020a17090b1d1200b001b9cfbfbf00sm351105pjb.40.2022.03.02.18.33.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Mar 2022 18:33:43 -0800 (PST) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 579D11140AF9; Thu, 3 Mar 2022 13:03:41 +1030 (ACDT) Date: Thu, 3 Mar 2022 13:03:41 +1030 From: Alan Modra To: binutils@sourceware.org Subject: PowerPC64 DT_RELR relative reloc addresses Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-3037.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: Thu, 03 Mar 2022 02:33:47 -0000 Section addresses can change between ppc64_elf_size_stubs and ppc64_elf_build_stubs due to .eh_frame editing. The idea of stashing r_offset final addresses calculated in ppc64_elf_size_stubs for use by ppc64_elf_build_stubs was never a good idea. Instead, we need to keep section/offset pairs. * elf64-ppc.c (struct ppc_link_hash_table): Delete relr_addr. Add relr section/offset array. (append_relr_off): Rewrite. Update all callers. (sort_relr): New function. (ppc64_elf_size_stubs): Adjust to suit new relative reloc stash. (ppc64_elf_build_stubs): Likewise. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index dd79c05bb61..89ce4cfba0d 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3269,10 +3269,14 @@ 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. */ + /* DT_RELR array of section/r_offset. */ size_t relr_alloc; size_t relr_count; - bfd_vma *relr_addr; + struct + { + asection *sec; + bfd_vma off; + } *relr; /* Statistics. */ unsigned long stub_count[ppc_stub_save_res]; @@ -13410,16 +13414,11 @@ 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; -} +/* Stash R_PPC64_RELATIVE reloc at input section SEC, r_offset OFF to + the array of such relocs. */ static bool -append_relr_off (struct ppc_link_hash_table *htab, bfd_vma off) +append_relr_off (struct ppc_link_hash_table *htab, asection *sec, bfd_vma off) { if (htab->relr_count >= htab->relr_alloc) { @@ -13427,16 +13426,51 @@ append_relr_off (struct ppc_link_hash_table *htab, bfd_vma off) 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) + htab->relr = bfd_realloc (htab->relr, + htab->relr_alloc * sizeof (*htab->relr)); + if (htab->relr == NULL) return false; } - htab->relr_addr[htab->relr_count++] = off; + htab->relr[htab->relr_count].sec = sec; + htab->relr[htab->relr_count].off = off; + htab->relr_count++; return true; } +/* qsort comparator for bfd_vma args. */ + +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; +} + +/* Produce a malloc'd sorted array of reloc addresses from the info + stored by append_relr_off. */ + +static bfd_vma * +sort_relr (struct ppc_link_hash_table *htab) +{ + bfd_vma *addr = bfd_malloc (htab->relr_count * sizeof (*addr)); + if (addr == NULL) + return NULL; + + for (size_t i = 0; i < htab->relr_count; i++) + addr[i] = (htab->relr[i].sec->output_section->vma + + htab->relr[i].sec->output_offset + + htab->relr[i].off); + + if (htab->relr_count > 1) + qsort (addr, htab->relr_count, sizeof (*addr), compare_relr_address); + + return addr; +} + +/* Look over GOT and PLT entries saved on elf_local_got_ents for all + all input files, stashing info about needed relative relocs. */ + static bool got_and_plt_relr_for_local_syms (struct bfd_link_info *info) { @@ -13484,10 +13518,7 @@ got_and_plt_relr_for_local_syms (struct bfd_link_info *info) && isym->st_shndx != SHN_ABS) { 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)) + if (!append_relr_off (htab, got, gent->got.offset)) { htab->stub_error = true; return false; @@ -13502,10 +13533,7 @@ got_and_plt_relr_for_local_syms (struct bfd_link_info *info) if (pent->plt.offset != (bfd_vma) -1 && ELF_ST_TYPE (isym->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)) + if (!append_relr_off (htab, htab->pltlocal, pent->plt.offset)) { if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); @@ -13525,6 +13553,9 @@ got_and_plt_relr_for_local_syms (struct bfd_link_info *info) return true; } +/* Stash info about needed GOT and PLT entry relative relocs for + global symbol H. */ + static bool got_and_plt_relr (struct elf_link_hash_entry *h, void *inf) { @@ -13556,10 +13587,7 @@ got_and_plt_relr (struct elf_link_hash_entry *h, void *inf) && 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)) + if (!append_relr_off (htab, got, gent->got.offset)) { htab->stub_error = true; return false; @@ -13571,10 +13599,7 @@ got_and_plt_relr (struct elf_link_hash_entry *h, void *inf) 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)) + if (!append_relr_off (htab, htab->pltlocal, pent->plt.offset)) { htab->stub_error = true; return false; @@ -13852,9 +13877,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) 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)) + if (!append_relr_off (htab, section, r_offset)) goto error_ret_free_internal; continue; } @@ -14205,9 +14228,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) 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))) + if (!append_relr_off (htab, htab->brlt, r_offset)) return false; if (!got_and_plt_relr_for_local_syms (info)) @@ -14216,28 +14237,28 @@ ppc64_elf_size_stubs (struct bfd_link_info *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); + bfd_vma *relr_addr = sort_relr (htab); + if (htab->relr_count != 0 && relr_addr == NULL) + return false; size_t i = 0; while (i < htab->relr_count) { - bfd_vma base = htab->relr_addr[i]; + bfd_vma base = 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) + && 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) + && relr_addr[i] - base < 63 * 8 + && (relr_addr[i] - base) % 8 == 0) i++; if (i == start_i) break; @@ -14245,6 +14266,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info) base += 63 * 8; } } + free (relr_addr); } for (group = htab->group; group != NULL; group = group->next) @@ -15184,17 +15206,21 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, if (htab->elf.srelrdyn->contents == NULL) return false; + bfd_vma *relr_addr = sort_relr (htab); + if (htab->relr_count != 0 && relr_addr == 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_vma base = 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) + && relr_addr[i] == base) { htab->stub_error = true; i++; @@ -15204,10 +15230,10 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, { bfd_vma bits = 0; while (i < htab->relr_count - && htab->relr_addr[i] - base < 63 * 8 - && (htab->relr_addr[i] - base) % 8 == 0) + && relr_addr[i] - base < 63 * 8 + && (relr_addr[i] - base) % 8 == 0) { - bits |= (bfd_vma) 1 << ((htab->relr_addr[i] - base) / 8); + bits |= (bfd_vma) 1 << ((relr_addr[i] - base) / 8); i++; } if (bits == 0) @@ -15217,6 +15243,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, base += 63 * 8; } } + free (relr_addr); /* Pad any excess with 1's, a do-nothing encoding. */ while ((size_t) (loc - htab->elf.srelrdyn->contents) < htab->elf.srelrdyn->size) -- Alan Modra Australia Development Lab, IBM