diff --git a/lld/test/ELF/gc-sections-retain.s b/lld/test/ELF/gc-sections-retain.s index edde321754ab78..196fc73fa0d430 100644 --- a/lld/test/ELF/gc-sections-retain.s +++ b/lld/test/ELF/gc-sections-retain.s @@ -8,11 +8,6 @@ # RUN: ld.lld -r -e _start --gc-sections --print-gc-sections %t.o -o %t.ro | count 0 # RUN: llvm-readobj -hS %t.ro | FileCheck %s -## SHF_GNU_RETAIN has no significance in executables/shared objects. Multiple -## OSABI values can benefit from this flag. Test that we don't change EI_OSABI, -## even for relocatable output. -# CHECK: OS/ABI: SystemV (0x0) - # CHECK: Name: .retain # CHECK-NEXT: Type: SHT_PROGBITS # CHECK-NEXT: Flags [ diff --git a/llvm/include/llvm/MC/MCObjectWriter.h b/llvm/include/llvm/MC/MCObjectWriter.h index ddc2301c04c13d..d2a2f1a13ff5e1 100644 --- a/llvm/include/llvm/MC/MCObjectWriter.h +++ b/llvm/include/llvm/MC/MCObjectWriter.h @@ -85,6 +85,9 @@ class MCObjectWriter { bool InSet, bool IsPCRel) const; + /// ELF only. Mark that we have seen GNU ABI usage (e.g. SHF_GNU_RETAIN). + virtual void markGnuAbi() {} + /// Tell the object writer to emit an address-significance table during /// writeObject(). If this function is not called, all symbols are treated as /// address-significant. diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index e635a47680da88..b837e6e5330556 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -222,6 +222,7 @@ class ELFObjectWriter : public MCObjectWriter { DenseMap Renames; + bool SeenGnuAbi = false; bool EmitAddrsigSection = false; std::vector AddrsigSyms; @@ -237,6 +238,7 @@ class ELFObjectWriter : public MCObjectWriter { : TargetObjectWriter(std::move(MOTW)) {} void reset() override { + SeenGnuAbi = false; Relocations.clear(); Renames.clear(); MCObjectWriter::reset(); @@ -260,6 +262,8 @@ class ELFObjectWriter : public MCObjectWriter { void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void markGnuAbi() override { SeenGnuAbi = true; } + bool seenGnuAbi() const { return SeenGnuAbi; } void emitAddrsigSection() override { EmitAddrsigSection = true; } void addAddrsigSymbol(const MCSymbol *Sym) override { AddrsigSyms.push_back(Sym); @@ -412,7 +416,10 @@ void ELFWriter::writeHeader(const MCAssembler &Asm) { W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION] // e_ident[EI_OSABI] - W.OS << char(OWriter.TargetObjectWriter->getOSABI()); + uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI(); + W.OS << char(OSABI == ELF::ELFOSABI_NONE && OWriter.seenGnuAbi() + ? ELF::ELFOSABI_GNU + : OSABI); // e_ident[EI_ABIVERSION] W.OS << char(OWriter.TargetObjectWriter->getABIVersion()); diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 12a8575a5f7256..5a6c042333dcc1 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -156,6 +156,8 @@ void MCELFStreamer::changeSection(MCSection *Section, const MCSymbol *Grp = SectionELF->getGroup(); if (Grp) Asm.registerSymbol(*Grp); + if (SectionELF->getFlags() & ELF::SHF_GNU_RETAIN) + Asm.getWriter().markGnuAbi(); changeSectionImpl(Section, Subsection); Asm.registerSymbol(*Section->getBeginSymbol()); diff --git a/llvm/test/MC/ELF/section-gnu.s b/llvm/test/MC/ELF/section-gnu.s index 5fc72d99a9713f..67a09a62d48569 100644 --- a/llvm/test/MC/ELF/section-gnu.s +++ b/llvm/test/MC/ELF/section-gnu.s @@ -1,10 +1,12 @@ # RUN: llvm-mc -triple=x86_64 %s | FileCheck %s --check-prefix=ASM -# RUN: llvm-mc -filetype=obj -triple=x86_64 %s | llvm-readobj -hS - | FileCheck %s --check-prefix=OBJ +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s | llvm-readobj -hS - | FileCheck %s --check-prefixes=GNU,OBJ +# RUN: llvm-mc -filetype=obj -triple=aarch64-freebsd %s | llvm-readobj -hS - | FileCheck %s --check-prefixes=FREEBSD,OBJ # ASM: .section retain,"aR",@progbits -## Note: GNU as sets OSABI to GNU. -# OBJ: OS/ABI: SystemV (0x0) +## ELFOSABI_NONE is changed to ELFOSABI_GNU. Other OSABI values are unchanged. +# GNU: OS/ABI: GNU/Linux +# FREEBSD: OS/ABI: FreeBSD # OBJ: Name: retain # OBJ-NEXT: Type: SHT_PROGBITS