[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