From patchwork Sun Aug 2 12:57:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 140424 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2FA3B4BA7983 for ; Sun, 2 Aug 2026 12:58:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2FA3B4BA7983 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=dsnTjk77 X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by sourceware.org (Postfix) with ESMTPS id 242B04BA23FD for ; Sun, 2 Aug 2026 12:57:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 242B04BA23FD Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 242B04BA23FD Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1034 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785675478; cv=none; b=YTt1AHxl/dsFdtQHzXclGo7TUEXMuu/NlTWVd44JfdcmDALN4Yl6inJfP+6cnf+ZWPjv+Tz3PwzRGDNh2BkZufxioYtmJhlt5YWSmOrxwNjW5RM2Ipo3JX3K3BiFoUHPlyeRKlZim8OlSMSGC6SiK/f7SWReJGKDqgqtav2ORPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785675478; c=relaxed/simple; bh=pEufubWM0/Tv0txai7VCVdYTJBxJgzIi6wtzP7WS29c=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=Hk9C9UfZQffHV8CiJKzZogprjEVcpahpgNHIYd1n1GcKOUFkBuWsE73OIcKv5OESQyf+WiErXA0ZMPTZSq5YX9T83LVmhSRqcoC+KXGauYgvQ/FSovxyUJbZqyoVHhO7e7FvCkeZYpT3AgWj4yBpUnjxP45TieE6hAv3Ato78hA= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=dsnTjk77 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 242B04BA23FD Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-38e42560ebcso1789441a91.1 for ; Sun, 02 Aug 2026 05:57:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785675477; x=1786280277; darn=sourceware.org; h=content-disposition:content-type:mime-version:message-id:subject:to :from:date:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Srd4O5jACOwORp+ikKzvD8Tt/rmBp1l5eIVwYPdz/rw=; b=dsnTjk7790ZbZX7IJXdqlhwUfPMdyX0rsrinFUMS1ckRwTvXXURsMS2nFQSButYRYN DgOCUrK6gnHsbDnRK9JjoZfGXMT1VHxyMLXATJUsx4CQxO09Bj+MU+7wHbENYpUnBnsX 9p8gSlnhfxtc5HXtl+7JVivcFInSlznIG8EFAl4hNUWtW31HV/xBoQZZHY7OuzHzgu7P 5llWMKxMmhGNe5NOZBSDJXznokjStc4wk8eWqV+Su20vGR2Z522WpqIFw6veyPUPf4Ik nEoMJawfA25ZDdyEiK0WZkvQ/j2qKcNmvtb64e7Nfbh8JCxXXsnm2dpApq4bHjIU/ys6 QlTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785675477; x=1786280277; h=content-disposition:content-type:mime-version:message-id:subject:to :from:date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Srd4O5jACOwORp+ikKzvD8Tt/rmBp1l5eIVwYPdz/rw=; b=fpPeDSTtzSEey1iiRk2TzdojT/7LlaSqkWRUdvm2XdpgeOAjl7EpYUAXi0a+G4qlVU DhjOU+BJMNYS+dv5RLr45hm2rp/r+c+5h/HYL5SyTZ+p877ijN7HaZdl2+/gZ5fYlXO+ QZTTaUBA2fVhPdgUhIO8XAdyxkMlabBXcTWUHa+y12tHvw1bsAYUKoaBTI2tQBbb8BxK 4XUQdAKDFHz1K42/vU4PaF+M0pv1IRp7TQ0nbFSTkKg5h+iikZAo7OIbpJ5ljU+Apmdd t0UaL3dAYBD9ukGbQ8dufiB9G64SxETeWJiLV0l0uzjUTJz2FEwkVl4e0e86kU/r2OVh ICCA== X-Gm-Message-State: AOJu0YwGqRrWvtVMG3R3eTdQrK20pe/xejGB355SaSbkAfxmwIdzk75b SYpIBHpGrmTfuMMkua6uIfCVL1WJEBtxSzlvhz9+kAVLuiA0GJzG6ZtccpC7TQ== X-Gm-Gg: AR+sD13waEma8HQzgxTZoknUkMrf2ppMWoSwzxIDS5lKyYxY59+z4wp3dAjWPD6zbwK VXBmdHa5/Hw54th0OMxfgN2AYxL7eu30suwdkPBDxE5cpcLoMd60S+n91nUy7Mc7VR96d+sikOk idSezEyu2y6phhu1P/bEBjOrmnzy6Ec462Mn/qRf1QPgHsBHaPyvq0GiO7D+5Kic2RaARKEq2yS 1fMzTIVS9TOE+NU9QHEBCJow2nlZQSPa3xw66Kdn+J+rYT7R3+WzM3r+V1h6kQqxQK1ItNZrIT0 JSlxWQ/0tFrZ0BNebzNYEESDH9y+ue3ri9FppQ46yFhj54Qgv6machJJP6ruAxJGXfonOjST8Dj 3XTO2uGzmVsHRb58LQxg0Hsa3N6MagG+kGFp/eBhlRPKQ3TAtoAwzHJ6YKrA1+Bg42E1uGIPQr1 38KEI57eGU3ZUuUm125b3+09KEgP6fMa+L2w+oOV1xDfRKH/n8piPuiICh5A2cKL1wWU+rNuRPa rQ= X-Received: by 2002:a17:90b:1c04:b0:36b:77b9:5c8c with SMTP id 98e67ed59e1d1-38fbc489d7amr5701303a91.17.1785675476827; Sun, 02 Aug 2026 05:57:56 -0700 (PDT) Received: from squeak.grove.modra.org ([2406:3400:51d:8cc0:eabd:d416:9aae:7676]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-38fb2f657a1sm2761889a91.7.2026.08.02.05.57.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 05:57:55 -0700 (PDT) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id E7E331141402; Sun, 02 Aug 2026 22:27:52 +0930 (ACST) Date: Sun, 2 Aug 2026 22:27:52 +0930 From: Alan Modra To: binutils@sourceware.org Subject: memory mayhem in _bfd_elf_link_read_relocs Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-3029.5 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 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Commit c6291d749a broke linking of objects with both REL and RELA relocations applying to the same section. Unfortunately there appears to be no test for this in the testsuite: The test added along with the original support in commit 19dd00f891 verified creation of such objects, but not their use as linker inputs. If you do take the output of ld-tic6x/pcrel-reloc-local-r-rel-rela.d and feed it through another ld -r stage, you typically get malloc/free corruption aborts. The problem is that the REL buffer is being reused for RELA. Commit 3a8864b3aa neglected to update the function comment. This patch fixes both of these problems and extends the tic6c testcase with a trick to insert an extra ld -r link stage. bfd/ * elflink.c (_bfd_elf_link_info_read_relocs): Correct function description. Correct buffer handling for the case where both rel.hdr and rela.hdr are non-NULL. Rename variables for clarity. ld/ * testsuite/ld-tic6x/pcrel-reloc-local-r-rel-rela.d: Add an extra ld -r stage. diff --git a/bfd/elflink.c b/bfd/elflink.c index 0af9837a28c..11da9a744e2 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2885,12 +2885,11 @@ elf_link_read_relocs_from_section (bfd *abfd, cached. If the EXTERNAL_RELOCS and INTERNAL_RELOCS arguments are not NULL, they are used as buffers to read into. They are known to be large enough. If the INTERNAL_RELOCS relocs argument is NULL, - the return value is allocated using either malloc or bfd_alloc, - according to the KEEP_MEMORY argument. If O has two relocation - sections (both REL and RELA relocations), then the REL_HDR + the return value is allocated using malloc. If O has both a REL + relocation section and a RELA relocation section, then the REL relocations will appear first in INTERNAL_RELOCS, followed by the - RELA_HDR relocations. If INFO isn't NULL and KEEP_MEMORY is true, - update cache_size. */ + RELA relocations. If KEEP_MEMORY is true the internal relocs are + cached, with info->cache_size updated if INFO is non-NULL. */ Elf_Internal_Rela * _bfd_elf_link_info_read_relocs (bfd *abfd, @@ -2900,9 +2899,9 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, Elf_Internal_Rela *internal_relocs, bool keep_memory) { - void *alloc1 = NULL; - size_t alloc1_size; - Elf_Internal_Rela *alloc2 = NULL; + void *ext_alloc1, *ext_alloc2; + size_t ext_mmap1, ext_mmap2; + Elf_Internal_Rela *int_alloc = NULL; elf_backend_data *bed = get_elf_backend_data (abfd); struct bfd_elf_section_data *esdo = elf_section_data (o); Elf_Internal_Rela *internal_rela_relocs; @@ -2920,46 +2919,58 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela); if (keep_memory && info) info->cache_size += size; - internal_relocs = alloc2 = bfd_malloc (size); + internal_relocs = int_alloc = bfd_malloc (size); if (internal_relocs == NULL) return NULL; } - alloc1 = external_relocs; + ext_alloc1 = external_relocs; + ext_mmap1 = 0; internal_rela_relocs = internal_relocs; if (esdo->rel.hdr) { if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr, - &alloc1, &alloc1_size, + &ext_alloc1, &ext_mmap1, internal_relocs)) - goto error_return; - external_relocs = (((bfd_byte *) external_relocs) - + esdo->rel.hdr->sh_size); + { + internal_relocs = NULL; + goto out1; + } + if (external_relocs != NULL) + external_relocs = (((bfd_byte *) external_relocs) + + esdo->rel.hdr->sh_size); internal_rela_relocs += (NUM_SHDR_ENTRIES (esdo->rel.hdr) * bed->s->int_rels_per_ext_rel); } + ext_alloc2 = external_relocs; + ext_mmap2 = 0; if (esdo->rela.hdr - && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, - &alloc1, &alloc1_size, - internal_rela_relocs))) - goto error_return; + && !elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, + &ext_alloc2, &ext_mmap2, + internal_rela_relocs)) + internal_relocs = NULL; - /* Cache the results for next time, if we can. */ - if (keep_memory) - esdo->relocs = internal_relocs; + /* If the external relocs were mmap'd then we want to munmap them + regardless of whether or not an external_relocs buffer was + provided. If they were not mmap'd then we only want to free + buffers allocated here. */ + if (ext_mmap2 != 0 || external_relocs == NULL) + _bfd_munmap_temporary (ext_alloc2, ext_mmap2); + out1: + if (ext_mmap1 != 0 || external_relocs == NULL) + _bfd_munmap_temporary (ext_alloc1, ext_mmap1); - _bfd_munmap_temporary (alloc1, alloc1_size); + /* Don't free int_alloc, if we are returning it under the name of + internal_relocs. */ + if (internal_relocs == NULL) + free (int_alloc); - /* Don't free alloc2, since if it was allocated we are passing it - back (under the name of internal_relocs). */ + /* Cache the results for next time, if we can. */ + else if (keep_memory) + esdo->relocs = internal_relocs; return internal_relocs; - - error_return: - _bfd_munmap_temporary (alloc1, alloc1_size); - free (alloc2); - return NULL; } /* This is similar to _bfd_elf_link_info_read_relocs, except for that diff --git a/ld/testsuite/ld-tic6x/pcrel-reloc-local-r-rel-rela.d b/ld/testsuite/ld-tic6x/pcrel-reloc-local-r-rel-rela.d index 81cfc6cc5a6..43db26133f3 100644 --- a/ld/testsuite/ld-tic6x/pcrel-reloc-local-r-rel-rela.d +++ b/ld/testsuite/ld-tic6x/pcrel-reloc-local-r-rel-rela.d @@ -1,8 +1,9 @@ #name: C6X PC-relative relocations, local symbols, -r, mixed link of REL/RELA -#as: -mlittle-endian -#ld: -r -melf32_tic6x_le #source: pcrel-reloc-local-1.s -mgenerate-rel #source: pcrel-reloc-local-2.s +#as: -mlittle-endian +#ld: -r -melf32_tic6x_le +#ld_after_inputfiles: && $LD -r -o tmpdir/pcrel-reloc-local-r-rel-rela.o tmpdir/dump #objdump: -dr .*: *file format elf32-tic6x-le