From a1585b671d1a5cc53cc4b72ca92467586679dbc5 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Wed, 11 Jun 2025 12:03:38 +0100 Subject: [PATCH] [IRGen] Don't use GOTPCREL relocations for x86 ELF. Unforunately, x86 ELF linkers like to optimize GOTPCREL relocations by replacing `mov` instructions that go via the GOT with `lea` instructions that do not. That would be fine, but they aren't very selective and will happily perform this transformation in non-code sections if they think that the bytes before a relocation look like a `mov` instruction. This corrupts our metadata. rdar://148168098 --- lib/IRGen/GenDecl.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 10fcf2ecbf46a..9d1b18005f400 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3699,13 +3699,15 @@ static llvm::GlobalVariable *createGOTEquivalent(IRGenModule &IGM, llvm::GlobalValue::PrivateLinkage, global, llvm::Twine("got.") + globalName); - + // rdar://problem/53836960: i386 ld64 also mis-links relative references // to GOT entries. // rdar://problem/59782487: issue with on-device JITd expressions. // The JIT gets confused by private vars accessed across object files. + // rdar://148168098: ELF x86 GOTPCREL relaxation can break metadata. if (!IGM.getOptions().UseJIT && - (!IGM.Triple.isOSDarwin() || IGM.Triple.getArch() != llvm::Triple::x86)) { + (!IGM.Triple.isOSDarwin() || IGM.Triple.getArch() != llvm::Triple::x86) && + (!IGM.Triple.isOSBinFormatELF() || !IGM.Triple.isX86())) { gotEquivalent->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); } else { ApplyIRLinkage(IRLinkage::InternalLinkOnceODR)