[llvm] 42e391e - [ELF] Use SHF_SUNW_NODISCARD instead of SHF_GNU_RETAIN on Solaris
Rainer Orth via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 23 06:42:10 PST 2022
Author: Rainer Orth
Date: 2022-02-23T15:41:43+01:00
New Revision: 42e391e4ca848e152bf8cdb072ed3ca2a394da2b
URL: https://github.com/llvm/llvm-project/commit/42e391e4ca848e152bf8cdb072ed3ca2a394da2b
DIFF: https://github.com/llvm/llvm-project/commit/42e391e4ca848e152bf8cdb072ed3ca2a394da2b.diff
LOG: [ELF] Use SHF_SUNW_NODISCARD instead of SHF_GNU_RETAIN on Solaris
Instead of the GNU extension `SHF_GNU_RETAIN`, Solaris provides equivalent
functionality with `SHF_SUNW_NODISCARD`. This patch implements the necessary
support.
Tested on `sparcv9-sun-solaris2.11`, `amd64-pc-solaris2.11`, and
`x86_64-pc-linux-gnu`.
Differential Revision: https://reviews.llvm.org/D107955
Added:
llvm/test/tools/llvm-readobj/ELF/section-flags-solaris.test
llvm/test/tools/obj2yaml/ELF/retain-section.yaml
llvm/test/tools/yaml2obj/ELF/retain-section.yaml
Modified:
llvm/include/llvm/BinaryFormat/ELF.h
llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/tools/llvm-readobj/ELFDumper.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index bc4b677c75a15..473fa41e4bd11 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1042,6 +1042,9 @@ enum : unsigned {
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
index 92a9f78ce7bfd..4ef0bdd1df688 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -720,6 +720,7 @@ struct Object {
llvm_unreachable("the section header table chunk must always be present");
}
+ ELF_ELFOSABI getOSAbi() const;
unsigned getMachine() const;
};
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 48803cae1bd9c..96c13ea1544fc 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -29,6 +29,8 @@ namespace llvm {
ELFYAML::Chunk::~Chunk() = default;
namespace ELFYAML {
+ELF_ELFOSABI Object::getOSAbi() const { return Header.OSABI; }
+
unsigned Object::getMachine() const {
if (Header.Machine)
return *Header.Machine;
@@ -706,7 +708,14 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
BCase(SHF_GROUP);
BCase(SHF_TLS);
BCase(SHF_COMPRESSED);
- BCase(SHF_GNU_RETAIN);
+ switch (Object->getOSAbi()) {
+ case ELF::ELFOSABI_SOLARIS:
+ BCase(SHF_SUNW_NODISCARD);
+ break;
+ default:
+ BCase(SHF_GNU_RETAIN);
+ break;
+ }
switch (Object->getMachine()) {
case ELF::EM_ARM:
BCase(SHF_ARM_PURECODE);
diff --git a/llvm/test/tools/llvm-readobj/ELF/section-flags-solaris.test b/llvm/test/tools/llvm-readobj/ELF/section-flags-solaris.test
new file mode 100644
index 0000000000000..2539383b1af8e
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/section-flags-solaris.test
@@ -0,0 +1,36 @@
+## Here we test how Solaris specific flags are dumped.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-readobj -S %t.o | FileCheck %s
+
+# CHECK: Name: .os.flags.low
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [ (0x100000)
+# CHECK-NEXT: SHF_SUNW_NODISCARD (0x100000)
+# CHECK-NEXT: ]
+# CHECK: Name: .os.flags.high
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [ (0xFE00000)
+# CHECK-NEXT: ]
+# CHECK: Name: .os.flags.mask
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [ (0xFF00000)
+# CHECK-NEXT: SHF_SUNW_NODISCARD (0x100000)
+# CHECK-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_SOLARIS
+ Type: ET_REL
+Sections:
+ - Name: .os.flags.low
+ Type: SHT_PROGBITS
+ ShFlags: 0x00100000
+ - Name: .os.flags.high
+ Type: SHT_PROGBITS
+ ShFlags: 0x0FE00000
+ - Name: .os.flags.mask
+ Type: SHT_PROGBITS
+ ShFlags: 0x0FF00000
diff --git a/llvm/test/tools/obj2yaml/ELF/retain-section.yaml b/llvm/test/tools/obj2yaml/ELF/retain-section.yaml
new file mode 100644
index 0000000000000..a8509fabab6cb
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/ELF/retain-section.yaml
@@ -0,0 +1,36 @@
+## Check handling of SHF_GNU_RETAIN and SHF_SUNW_NODISCARD section flags.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=GNU
+
+# GNU: Name: .gnu.retain
+# GNU-NEXT: Type: SHT_PROGBITS
+# GNU-NEXT: Flags: [ SHF_GNU_RETAIN ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+Sections:
+ - Name: .gnu.retain
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=SOLARIS
+
+# SOLARIS: Name: .sunw.nodiscard
+# SOLARIS-NEXT: Type: SHT_PROGBITS
+# SOLARIS-NEXT: Flags: [ SHF_SUNW_NODISCARD ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_SOLARIS
+ Type: ET_REL
+Sections:
+ - Name: .sunw.nodiscard
+ Type: SHT_PROGBITS
+ Flags: [ SHF_SUNW_NODISCARD ]
diff --git a/llvm/test/tools/yaml2obj/ELF/retain-section.yaml b/llvm/test/tools/yaml2obj/ELF/retain-section.yaml
new file mode 100644
index 0000000000000..26cc1daea7f24
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/ELF/retain-section.yaml
@@ -0,0 +1,74 @@
+## Check how yaml2obj handles retain (SHF_GNU_RETAIN and
+## SHF_SUNW_NODISCARD) section flags.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj --sections %t1 | FileCheck %s --check-prefix=GNU
+
+# GNU: Name: .gnu.retain
+# GNU-NEXT: Type: SHT_PROGBITS (0x1)
+# GNU-NEXT: Flags [ (0x200000)
+# GNU-NEXT: SHF_GNU_RETAIN (0x200000)
+# GNU-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+Sections:
+ - Name: .gnu.retain
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-readobj --sections %t2 | FileCheck %s --check-prefix=SOLARIS
+
+# SOLARIS: Name: .sunw.nodiscard
+# SOLARIS-NEXT: Type: SHT_PROGBITS (0x1)
+# SOLARIS-NEXT: Flags [ (0x100000)
+# SOLARIS-NEXT: SHF_SUNW_NODISCARD (0x100000)
+# SOLARIS-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_SOLARIS
+ Type: ET_REL
+Sections:
+ - Name: .sunw.nodiscard
+ Type: SHT_PROGBITS
+ Flags: [ SHF_SUNW_NODISCARD ]
+
+# RUN: not yaml2obj --docnum=3 %s 2>&1 | \
+# RUN: FileCheck %s --check-prefix=SOLARIS-GNU-ERR
+
+# SOLARIS-GNU-ERR: error: unknown bit value
+# SOLARIS-GNU-ERR-NEXT: Flags: [ SHF_GNU_RETAIN ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_SOLARIS
+ Type: ET_REL
+Sections:
+ - Name: .sunw.retain
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+
+# RUN: not yaml2obj --docnum=4 %s 2>&1 | \
+# RUN: FileCheck %s --check-prefix=GNU-SOLARIS-ERR
+
+# GNU-SOLARIS-ERR: error: unknown bit value
+# GNU-SOLARIS-ERR-NEXT: Flags: [ SHF_SUNW_NODISCARD ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+Sections:
+ - Name: .gnu.nodiscard
+ Type: SHT_PROGBITS
+ Flags: [ SHF_SUNW_NODISCARD ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 20264ad72b5d4..e1f69b4f45aa7 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1242,10 +1242,17 @@ const EnumEntry<unsigned> ElfSectionFlags[] = {
ENUM_ENT(SHF_GROUP, "G"),
ENUM_ENT(SHF_TLS, "T"),
ENUM_ENT(SHF_COMPRESSED, "C"),
- ENUM_ENT(SHF_GNU_RETAIN, "R"),
ENUM_ENT(SHF_EXCLUDE, "E"),
};
+const EnumEntry<unsigned> ElfGNUSectionFlags[] = {
+ ENUM_ENT(SHF_GNU_RETAIN, "R")
+};
+
+const EnumEntry<unsigned> ElfSolarisSectionFlags[] = {
+ ENUM_ENT(SHF_SUNW_NODISCARD, "R")
+};
+
const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
ENUM_ENT(XCORE_SHF_CP_SECTION, ""),
ENUM_ENT(XCORE_SHF_DP_SECTION, "")
@@ -1275,9 +1282,19 @@ const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {
};
static std::vector<EnumEntry<unsigned>>
-getSectionFlagsForTarget(unsigned EMachine) {
+getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) {
std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags),
std::end(ElfSectionFlags));
+ switch (EOSAbi) {
+ case ELFOSABI_SOLARIS:
+ Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags),
+ std::end(ElfSolarisSectionFlags));
+ break;
+ default:
+ Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags),
+ std::end(ElfGNUSectionFlags));
+ break;
+ }
switch (EMachine) {
case EM_ARM:
Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags),
@@ -1305,7 +1322,8 @@ getSectionFlagsForTarget(unsigned EMachine) {
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.
@@ -1316,7 +1334,7 @@ static std::string getGNUFlags(unsigned EMachine, uint64_t Flags) {
bool HasOSFlag = false;
bool HasProcFlag = false;
std::vector<EnumEntry<unsigned>> FlagsList =
- getSectionFlagsForTarget(EMachine);
+ getSectionFlagsForTarget(EOSAbi, EMachine);
while (Flags) {
// Take the least significant bit as a flag.
uint64_t Flag = Flags & -Flags;
@@ -3682,7 +3700,8 @@ template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {
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);
@@ -6503,7 +6522,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {
int SectionIndex = -1;
std::vector<EnumEntry<unsigned>> 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);
More information about the llvm-commits
mailing list