Skip to content

[IRGen] Don't use GOTPCREL relocations for x86 ELF. #82176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 13, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3736,13 +3736,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())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you happen to know offhand if the linker on other ELF platforms (like FreeBSD) is also affected by this bug?

Copy link
Contributor Author

@al45tair al45tair Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FreeBSD uses lld, which does have this problem (and, unlike the BFD linker, while it understands -no-relax and won't complain about it, it ignores it for the purposes of this particular optimisation).

Basically, lld, gold and the BFD linker all do this; only the BFD linker has a way to disable it, and none of them test whether they're looking at a code section first. They do all have a handful of things they exempt from this behaviour (though the exact set differs; BFD and lld have more exceptions than gold does), but sadly none of them check whether they're in a code section first.

I'm aware that in principle there might be a platform using some other ELF linker that doesn't do this, but even in that case, someone might choose to use one of the three linkers above that all do.

(It looks to me like mold may be such a linker, just at a quick glance.)

gotEquivalent->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
} else {
ApplyIRLinkage(IRLinkage::InternalLinkOnceODR)
Expand Down