From nobody Thu Aug 6 18:03:27 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hGFWg48QSz6nRX1 for ; Thu, 06 Aug 2026 18:03:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hGFWg1kyfz3gn6 for ; Thu, 06 Aug 2026 18:03:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786039407; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pLIIozqGXF3IhNM5vxnfUG6V/9GogAw4huF9Noi0j1I=; b=KrpbPBeJ5Ex4GygGusLssCQWxYK1oVAsiJVI3+t508YNx7oX1rxrjzfOmstP5TPzQqyvZo eKwZ+V6WuR9BwB3ZomrrRdpdakQDUY9xCLcSwTFqFMBWoQCOYiNPJQzBUGCwixTfdHLhTj ITTlo1i/+GMGh0/m5su2Ieu/7V5+8WEU1I3u/ModSXTawD8E49JXkwDtXxC+a3Iy18OCcT 3YLO6yLmf0xG6t7CYh8C8ro5HOb1ODuGdPxQAeLfXTuThd2veCM+8O0r+/WVxECn/d3EB7 A1vyFa9fV98l0jhHIYybg6KjAjXuWkTKFocRQoxwGjuzQMCtLaR53D/8b98+hg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786039407; a=rsa-sha256; cv=none; b=wYL/hFhQHgvcMsB/GLVhFKm3Oe0udqDIyywTVqFrgfCF1bmiuvdj20RPqSHCecvcUwE6CX nF4OhO+fwoDACjWjDqSt5f01Jcw2m5dGCZnr1/dKshYxXFXAB2lgY4otI/JIyvB2X2qxty FBrX0etjGnoZz70nOb2wQMsOhtyhzgZzyGmk4DImu40KUguRfmZgvRojJ7oGKKqlmj7bzj 96lq/JkkGlfdK5rXABNxJdxn7WHiTGjidpHeJ/3hIDrZd/OvZsQN5rXsPjKNI2M5vaoauJ FxOxuJrkke/9vSRNrYSI+ut3k+QPn+EO9E09JMFfZNAGKgqezNkzoaoCyoqGVg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786039407; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pLIIozqGXF3IhNM5vxnfUG6V/9GogAw4huF9Noi0j1I=; b=s5443jAhSNVi+36ysTRKHTogo97yGlYD81genbVX12aHJziETv5aDJr5gUHTQf3LsiWFq6 qIOjmQmrJpqzlfNvRV3W2AqUTvWtM3BFpIwGsi2b3sKsHBuBY3UJb2urZkCWKuRiLvs2h6 ePMNXUg8s3HlCEG0NE2hPK2O3PlX0ymTTvo8paiqr1i88Y2PtLKXDnWFmfnFUiv2M4ixGs AgFclWwvcOkTsvd6PbSEl0nn6AKAqkaEmFK3fhO5czL4aaZ0ykVUeuuVn7SOdqCWiD9+ip YQBoZInb5zLqu8DJyhNeOPW4iI5Gj4Qzv9Lpq8XX6dxfX65gywQFIgaCG5TS+w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hGFWg0pCVzWtq for ; Thu, 06 Aug 2026 18:03:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 32f59 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 06 Aug 2026 18:03:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Jessica Clarke Subject: git: 310a5a993ac8 - stable/15 - Merge commit 26bf39cdba0b from llvm-project (by Jessica Clarke): List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jrtc27 X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 310a5a993ac8ffba2edcdb8152688620c2f5e56f Auto-Submitted: auto-generated Date: Thu, 06 Aug 2026 18:03:27 +0000 Message-Id: <6a74cc6f.32f59.52351d9e@gitrepo.freebsd.org> The branch stable/15 has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=310a5a993ac8ffba2edcdb8152688620c2f5e56f commit 310a5a993ac8ffba2edcdb8152688620c2f5e56f Author: Jessica Clarke AuthorDate: 2026-07-27 16:54:04 +0000 Commit: Jessica Clarke CommitDate: 2026-08-06 18:02:32 +0000 Merge commit 26bf39cdba0b from llvm-project (by Jessica Clarke): [ELF][PowerPC] Don't assume TOC pointer is valid in IPLT entries (#207555) Unlike normal PLT entries, IPLT entries can be called indirectly even when in PIEs/DSOs, and so there's no guarantee on what's in the TOC pointer register at that time. Therefore we must emit variants of the existing code that work without it, whether r12-relative (playing the same role as MIPS's $25) in the same number of instructions, or first retrieving PC in an i386-like manner, being careful not to clobber LR. On 32-bit PowerPC even direct calls to IPLT entries face the same issue, since we'd use the TOC base of the resolver, which may not be the same as the caller, even within the same object. Normal canonical PLTs still look broken on 64-bit PowerPC as they use the TOC pointer register too, and similarly on 32-bit PowerPC for PIEs. We should probably treat these cases the same as PIE on i386 (except including PDEs for 64-bit PowerPC), where it's an error due to the use of %ebx in PLT entries. Bump LLD_FREEBSD_VERSION for this fix as otherwise an existing system linker will be deemed new enough to use and produce broken kernels for TARGET=powerpc (regardless of TARGET_ARCH/MACHINE/MACHINE_ARCH) builds. PR: 294369 MFC after: 1 week (cherry picked from commit b68f2fe1932cbc9809245e2c5a2db2bc0944cc5d) --- contrib/llvm-project/lld/ELF/Arch/PPC.cpp | 13 +++--- contrib/llvm-project/lld/ELF/Arch/PPC64.cpp | 5 ++- contrib/llvm-project/lld/ELF/Thunks.cpp | 69 +++++++++++++++++++++-------- contrib/llvm-project/lld/ELF/Thunks.h | 9 ++-- lib/clang/include/lld/Common/Version.inc | 2 +- 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/contrib/llvm-project/lld/ELF/Arch/PPC.cpp b/contrib/llvm-project/lld/ELF/Arch/PPC.cpp index 60a0a38d5f23..96f831d2cc5d 100644 --- a/contrib/llvm-project/lld/ELF/Arch/PPC.cpp +++ b/contrib/llvm-project/lld/ELF/Arch/PPC.cpp @@ -77,7 +77,7 @@ void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) { if (!ctx.arg.isPic) { for (const Symbol *sym : cast(*ctx.in.plt).canonical_plts) { - writePPC32PltCallStub(ctx, buf, sym->getGotPltVA(ctx), nullptr, 0); + writePPC32PltCallStub(ctx, buf, glink, sym->getGotPltVA(ctx), nullptr, 0); buf += 16; glink += 16; } @@ -165,7 +165,7 @@ PPC::PPC(Ctx &ctx) : TargetInfo(ctx) { gotPltHeaderEntriesNum = 0; pltHeaderSize = 0; pltEntrySize = 4; - ipltEntrySize = 16; + ipltEntrySize = ctx.arg.isPic ? 32 : 16; needsThunks = true; @@ -180,10 +180,11 @@ PPC::PPC(Ctx &ctx) : TargetInfo(ctx) { } void PPC::writeIplt(uint8_t *buf, const Symbol &sym, - uint64_t /*pltEntryAddr*/) const { - // In -pie or -shared mode, assume r30 points to .got2+0x8000, and use a - // .got2.plt_pic32. thunk. - writePPC32PltCallStub(ctx, buf, sym.getGotPltVA(ctx), sym.file, 0x8000); + uint64_t pltEntryAddr) const { + // In -pie or -shared mode we can't rely on r30 for indirect calls, nor for + // direct calls with a different TOC base to the resolver. + writePPC32PltCallStub(ctx, buf, pltEntryAddr, sym.getGotPltVA(ctx), sym.file, + std::nullopt); } void PPC::writeGotHeader(uint8_t *buf) const { diff --git a/contrib/llvm-project/lld/ELF/Arch/PPC64.cpp b/contrib/llvm-project/lld/ELF/Arch/PPC64.cpp index 8e85cfab8a63..70fdbb0bbd19 100644 --- a/contrib/llvm-project/lld/ELF/Arch/PPC64.cpp +++ b/contrib/llvm-project/lld/ELF/Arch/PPC64.cpp @@ -1167,8 +1167,9 @@ void PPC64::writePlt(uint8_t *buf, const Symbol &sym, } void PPC64::writeIplt(uint8_t *buf, const Symbol &sym, - uint64_t /*pltEntryAddr*/) const { - writePPC64LoadAndBranch(ctx, buf, sym.getGotPltVA(ctx)); + uint64_t pltEntryAddr) const { + writePPC64LoadAndBranch(ctx, buf, pltEntryAddr, sym.getGotPltVA(ctx), + /*toc=*/false); } static std::pair toAddr16Rel(RelType type, uint64_t val) { diff --git a/contrib/llvm-project/lld/ELF/Thunks.cpp b/contrib/llvm-project/lld/ELF/Thunks.cpp index 45b9ab9530e0..a8ed74e65189 100644 --- a/contrib/llvm-project/lld/ELF/Thunks.cpp +++ b/contrib/llvm-project/lld/ELF/Thunks.cpp @@ -1316,8 +1316,9 @@ InputSection *MicroMipsR6Thunk::getTargetInputSection() const { return dyn_cast(dr.section); } -void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA, - const InputFile *file, int64_t addend) { +void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t p, + uint64_t gotPltVA, const InputFile *file, + std::optional addend) { if (!ctx.arg.isPic) { write32(ctx, buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha write32(ctx, buf + 4, 0x816b0000 | (uint16_t)gotPltVA); // lwz r11,l(r11) @@ -1326,34 +1327,52 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA, return; } uint32_t offset; - if (addend >= 0x8000) { + uint32_t reg; + uint64_t written = 0; + if (!addend) { + // We're a (position-independent) IPLT entry, so cannot assume anything + // about what value the caller left in r30 as this could be an indirect + // call. + write32(ctx, buf + 0, 0x7c0802a6); // mflr r0 + write32(ctx, buf + 4, 0x429f0005); // bcl 20, 31, 1f + write32(ctx, buf + 8, 0x7d6802a6); // 1: mflr r11 + write32(ctx, buf + 12, 0x7c0803a6); // mtlr r0 + offset = gotPltVA - p - 8; + reg = 11; + written = 16; + } else if (*addend >= 0x8000) { // The stub loads an address relative to r30 (.got2+Addend). Addend is // almost always 0x8000. The address of .got2 is different in another object // file, so a stub cannot be shared. + reg = 30; offset = gotPltVA - (ctx.in.ppc32Got2->getParent()->getVA() + - (file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + addend); + (file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + *addend); } else { // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is // currently the address of .got). + reg = 30; offset = gotPltVA - ctx.in.got->getVA(); } uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset; if (ha == 0) { - write32(ctx, buf + 0, 0x817e0000 | l); // lwz r11,l(r30) - write32(ctx, buf + 4, 0x7d6903a6); // mtctr r11 - write32(ctx, buf + 8, 0x4e800420); // bctr - write32(ctx, buf + 12, 0x60000000); // nop + write32(ctx, buf + written + 0, + 0x81600000 | (reg << 16) | l); // lwz r11,l(r[11|30]) + write32(ctx, buf + written + 4, 0x7d6903a6); // mtctr r11 + write32(ctx, buf + written + 8, 0x4e800420); // bctr + write32(ctx, buf + written + 12, 0x60000000); // nop } else { - write32(ctx, buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha - write32(ctx, buf + 4, 0x816b0000 | l); // lwz r11,l(r11) - write32(ctx, buf + 8, 0x7d6903a6); // mtctr r11 - write32(ctx, buf + 12, 0x4e800420); // bctr + write32(ctx, buf + written + 0, + 0x3d600000 | (reg << 16) | ha); // addis r11,r[11|30],ha + write32(ctx, buf + written + 4, 0x816b0000 | l); // lwz r11,l(r11) + write32(ctx, buf + written + 8, 0x7d6903a6); // mtctr r11 + write32(ctx, buf + written + 12, 0x4e800420); // bctr } } void PPC32PltCallStub::writeTo(uint8_t *buf) { - writePPC32PltCallStub(ctx, buf, destination.getGotPltVA(ctx), file, addend); + writePPC32PltCallStub(ctx, buf, getThunkTargetSym()->getVA(ctx), + destination.getGotPltVA(ctx), file, addend); } void PPC32PltCallStub::addSymbols(ThunkSection &isec) { @@ -1402,12 +1421,22 @@ void PPC32LongThunk::writeTo(uint8_t *buf) { write32(ctx, buf + 4, 0x4e800420); // bctr } -void elf::writePPC64LoadAndBranch(Ctx &ctx, uint8_t *buf, uint64_t addr) { - uint64_t offset = addr - getPPC64TocBase(ctx); +void elf::writePPC64LoadAndBranch(Ctx &ctx, uint8_t *buf, uint64_t p, + uint64_t addr, bool toc) { + uint64_t offset; + uint32_t reg; + if (toc) { + offset = addr - getPPC64TocBase(ctx); + reg = 2; + } else { + offset = addr - p; + reg = 12; + } uint16_t offHa = (offset + 0x8000) >> 16; uint16_t offLo = offset & 0xffff; - write32(ctx, buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa + write32(ctx, buf + 0, + 0x3d800000 | (reg << 16) | offHa); // addis r12, r[2|12], OffHa write32(ctx, buf + 4, 0xe98c0000 | offLo); // ld r12, OffLo(r12) write32(ctx, buf + 8, 0x7d8903a6); // mtctr r12 write32(ctx, buf + 12, 0x4e800420); // bctr @@ -1416,7 +1445,8 @@ void elf::writePPC64LoadAndBranch(Ctx &ctx, uint8_t *buf, uint64_t addr) { void PPC64PltCallStub::writeTo(uint8_t *buf) { // Save the TOC pointer to the save-slot reserved in the call frame. write32(ctx, buf + 0, 0xf8410018); // std r2,24(r1) - writePPC64LoadAndBranch(ctx, buf + 4, destination.getGotPltVA(ctx)); + writePPC64LoadAndBranch(ctx, buf + 4, getThunkTargetSym()->getVA(ctx) + 4, + destination.getGotPltVA(ctx)); } void PPC64PltCallStub::addSymbols(ThunkSection &isec) { @@ -1458,7 +1488,8 @@ void PPC64R2SaveStub::writeTo(uint8_t *buf) { ctx.in.ppc64LongBranchTarget->addEntry(&destination, addend); const uint64_t addr = ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend); - writePPC64LoadAndBranch(ctx, buf + 4, addr); + writePPC64LoadAndBranch(ctx, buf + 4, getThunkTargetSym()->getVA(ctx) + 4, + addr); } } @@ -1520,7 +1551,7 @@ bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec, void PPC64LongBranchThunk::writeTo(uint8_t *buf) { uint64_t addr = ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend); - writePPC64LoadAndBranch(ctx, buf, addr); + writePPC64LoadAndBranch(ctx, buf, getThunkTargetSym()->getVA(ctx), addr); } void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) { diff --git a/contrib/llvm-project/lld/ELF/Thunks.h b/contrib/llvm-project/lld/ELF/Thunks.h index a802827ba407..7903b6ae97a0 100644 --- a/contrib/llvm-project/lld/ELF/Thunks.h +++ b/contrib/llvm-project/lld/ELF/Thunks.h @@ -83,9 +83,12 @@ std::unique_ptr addThunk(Ctx &, const InputSection &isec, // are restricted. std::unique_ptr addLandingPadThunk(Ctx &, Symbol &s, int64_t a); -void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t gotPltVA, - const InputFile *file, int64_t addend); -void writePPC64LoadAndBranch(Ctx &, uint8_t *buf, uint64_t addr); +// Call with addend as nullopt for an IPLT entry with no valid TOC pointer +void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t p, uint64_t gotPltVA, + const InputFile *file, + std::optional addend); +void writePPC64LoadAndBranch(Ctx &, uint8_t *buf, uint64_t p, uint64_t addr, + bool toc = true); } // namespace lld::elf diff --git a/lib/clang/include/lld/Common/Version.inc b/lib/clang/include/lld/Common/Version.inc index 0e69f9627120..9393fe18c2fc 100644 --- a/lib/clang/include/lld/Common/Version.inc +++ b/lib/clang/include/lld/Common/Version.inc @@ -1,4 +1,4 @@ // Local identifier in __FreeBSD_version style -#define LLD_FREEBSD_VERSION 1500001 +#define LLD_FREEBSD_VERSION 1500002 #define LLD_VERSION_STRING "21.1.8 (FreeBSD llvmorg-21.1.8-0-g2078da43e25a-" __XSTRING(LLD_FREEBSD_VERSION) ")"