diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1025,6 +1025,9 @@ SHF_MASKOS = 0x0ff00000, + // Solaris equivalent of SHF_GNU_RETAIN. + SHF_SUNW_NODISCARD = 0x00100000, + // Bits indicating processor-specific flags. SHF_MASKPROC = 0xf0000000, diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -720,6 +720,7 @@ llvm_unreachable("the section header table chunk must always be present"); } + ELF_ELFOSABI getOSAbi() const; unsigned getMachine() const; }; diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -677,9 +677,10 @@ } if (Retain) { - if ((Ctx.getAsmInfo()->useIntegratedAssembler() || - Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) && - !TM.getTargetTriple().isOSSolaris()) + if (TM.getTargetTriple().isOSSolaris()) + Flags |= ELF::SHF_SUNW_NODISCARD; + else if (Ctx.getAsmInfo()->useIntegratedAssembler() || + Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) Flags |= ELF::SHF_GNU_RETAIN; return NextUniqueID++; } @@ -856,12 +857,15 @@ EmitUniqueSection = true; Flags |= ELF::SHF_LINK_ORDER; } - if (Retain && - (Ctx.getAsmInfo()->useIntegratedAssembler() || - Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) && - !TM.getTargetTriple().isOSSolaris()) { - EmitUniqueSection = true; - Flags |= ELF::SHF_GNU_RETAIN; + if (Retain) { + if (TM.getTargetTriple().isOSSolaris()) { + EmitUniqueSection = true; + Flags |= ELF::SHF_SUNW_NODISCARD; + } else if (Ctx.getAsmInfo()->useIntegratedAssembler() || + Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) { + EmitUniqueSection = true; + Flags |= ELF::SHF_GNU_RETAIN; + } } MCSectionELF *Section = selectELFSectionForGlobal( diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -284,7 +284,8 @@ return false; } -static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { +static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr, + bool *UseLastGroup) { unsigned flags = 0; // If a valid numerical value is set for the section flag, use it verbatim @@ -333,7 +334,10 @@ flags |= ELF::SHF_GROUP; break; case 'R': - flags |= ELF::SHF_GNU_RETAIN; + if (TT.isOSSolaris()) + flags |= ELF::SHF_SUNW_NODISCARD; + else + flags |= ELF::SHF_GNU_RETAIN; break; case '?': *UseLastGroup = true; @@ -571,7 +575,8 @@ } else { StringRef FlagsStr = getTok().getStringContents(); Lex(); - extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); + extraFlags = parseSectionFlags(getContext().getTargetTriple(), FlagsStr, + &UseLastGroup); } if (extraFlags == -1U) diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/lib/MC/MCSectionELF.cpp @@ -105,6 +105,11 @@ if (Flags & ELF::SHF_GNU_RETAIN) OS << 'R'; + // If there are os-specific flags, print them. + if (T.isOSSolaris()) + if (Flags & ELF::SHF_SUNW_NODISCARD) + OS << 'R'; + // If there are target-specific flags, print them. Triple::ArchType Arch = T.getArch(); if (Arch == Triple::xcore) { diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -29,6 +29,8 @@ ELFYAML::Chunk::~Chunk() = default; namespace ELFYAML { +ELF_ELFOSABI Object::getOSAbi() const { return Header.OSABI; } + unsigned Object::getMachine() const { if (Header.Machine) return *Header.Machine; @@ -688,6 +690,14 @@ BCase(SHF_TLS); BCase(SHF_COMPRESSED); BCase(SHF_GNU_RETAIN); + switch (Object->getOSAbi()) { + case ELF::ELFOSABI_SOLARIS: + BCase(SHF_SUNW_NODISCARD); + break; + default: + // Nothing to do. + break; + } switch (Object->getMachine()) { case ELF::EM_ARM: BCase(SHF_ARM_PURECODE); diff --git a/llvm/test/CodeGen/X86/elf-retain.ll b/llvm/test/CodeGen/X86/elf-retain.ll --- a/llvm/test/CodeGen/X86/elf-retain.ll +++ b/llvm/test/CodeGen/X86/elf-retain.ll @@ -3,6 +3,8 @@ ; RUN: llc -mtriple=x86_64 -data-sections=1 < %s | FileCheck %s ; RUN: llc -mtriple=x86_64 -no-integrated-as -binutils-version=2.36 < %s | FileCheck %s ; RUN: llc -mtriple=x86_64 -no-integrated-as -binutils-version=2.35 < %s | FileCheck %s --check-prefix=OLDGAS +; Solaris uses the equivalent SHF_SUNW_NODISCARD flag, also represented as "R". +; RUN: llc -mtriple=x86_64-solaris < %s | FileCheck %s ; RUN: llc -mtriple=x86_64 -data-sections=1 -unique-section-names=0 < %s | FileCheck %s --check-prefix=NOUNIQUE diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1224,6 +1224,9 @@ ENUM_ENT(SHF_EXCLUDE, "E"), }; +static const EnumEntry ElfSolarisSectionFlags[] = { + ENUM_ENT(SHF_SUNW_NODISCARD, "R")}; + static const EnumEntry ElfXCoreSectionFlags[] = { ENUM_ENT(XCORE_SHF_CP_SECTION, ""), ENUM_ENT(XCORE_SHF_DP_SECTION, "") @@ -1253,9 +1256,17 @@ }; static std::vector> -getSectionFlagsForTarget(unsigned EMachine) { +getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) { std::vector> Ret(std::begin(ElfSectionFlags), std::end(ElfSectionFlags)); + switch (EOSAbi) { + case ELFOSABI_SOLARIS: + Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags), + std::end(ElfSolarisSectionFlags)); + break; + default: + break; + } switch (EMachine) { case EM_ARM: Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags), @@ -1283,7 +1294,8 @@ return Ret; } -static std::string getGNUFlags(unsigned EMachine, uint64_t Flags) { +static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine, + uint64_t Flags) { // Here we are trying to build the flags string in the same way as GNU does. // It is not that straightforward. Imagine we have sh_flags == 0x90000000. // SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000. @@ -1294,7 +1306,7 @@ bool HasOSFlag = false; bool HasProcFlag = false; std::vector> FlagsList = - getSectionFlagsForTarget(EMachine); + getSectionFlagsForTarget(EOSAbi, EMachine); while (Flags) { // Take the least significant bit as a flag. uint64_t Flag = Flags & -Flags; @@ -3635,7 +3647,8 @@ Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6)); Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); - Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_machine, Sec.sh_flags); + Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI], + this->Obj.getHeader().e_machine, Sec.sh_flags); Fields[8].Str = to_string(Sec.sh_link); Fields[9].Str = to_string(Sec.sh_info); Fields[10].Str = to_string(Sec.sh_addralign); @@ -6384,7 +6397,8 @@ int SectionIndex = -1; std::vector> FlagsList = - getSectionFlagsForTarget(this->Obj.getHeader().e_machine); + getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI], + this->Obj.getHeader().e_machine); for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { DictScope SectionD(W, "Section"); W.printNumber("Index", ++SectionIndex);