forked from OSchip/llvm-project
[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
This commit is contained in:
parent
03e6efb8c2
commit
42e391e4ca
|
@ -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,
|
||||
|
||||
|
|
|
@ -720,6 +720,7 @@ struct Object {
|
|||
llvm_unreachable("the section header table chunk must always be present");
|
||||
}
|
||||
|
||||
ELF_ELFOSABI getOSAbi() const;
|
||||
unsigned getMachine() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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 ]
|
|
@ -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 ]
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue