Index: llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test +++ llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test @@ -77,7 +77,6 @@ # MIPS-NEXT: Flags [ # MIPS-NEXT: SHF_ALLOC (0x2) # MIPS-NEXT: SHF_EXCLUDE (0x80000000) -# MIPS-NEXT: SHF_MASKPROC (0xF0000000) # MIPS-NEXT: SHF_MIPS_ADDR (0x40000000) # MIPS-NEXT: SHF_MIPS_GPREL (0x10000000) # MIPS-NEXT: SHF_MIPS_LOCAL (0x4000000) Index: llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test =================================================================== --- llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test +++ llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test @@ -27,12 +27,10 @@ # RUN: llvm-readelf -S %t-mips.o | FileCheck --check-prefix=MIPS-GNU %s # MIPS-GNU: [Nr] Name Type Address Off Size ES Flg Lk Inf Al -# MIPS-GNU: [ 1] .mips PROGBITS 00000000 000034 000000 00 Eop 0 0 0 +# MIPS-GNU: [ 1] .mips PROGBITS 00000000 000034 000000 00 op 0 0 0 # MIPS-LLVM: Flags [ (0xFF000000) # MIPS-LLVM-NEXT: SHF_EXCLUDE (0x80000000) -## FIXME: we should not print SHF_MASKPROC, because it is a mask value. -# MIPS-LLVM-NEXT: SHF_MASKPROC (0xF0000000) # MIPS-LLVM-NEXT: SHF_MIPS_ADDR (0x40000000) # MIPS-LLVM-NEXT: SHF_MIPS_GPREL (0x10000000) # MIPS-LLVM-NEXT: SHF_MIPS_LOCAL (0x4000000) @@ -55,7 +53,35 @@ Flags: [ SHF_MIPS_NODUPES, SHF_MIPS_NAMES, SHF_MIPS_LOCAL, SHF_MIPS_NOSTRIP, SHF_MIPS_GPREL, SHF_MIPS_MERGE, SHF_MIPS_ADDR, SHF_MIPS_STRING ] -# RUN: yaml2obj --docnum 3 %s -o %t-x86_64.o +## Test what we print when an MIPS object when it has SHF_MIPS_STRING flag. +## SHF_MIPS_STRING has a value of 0x80000000, which matches the value of SHF_EXCLUDE. + +# RUN: yaml2obj --docnum 3 %s -o %t-mips-exclude.o +# RUN: llvm-readobj -S %t-mips-exclude.o | FileCheck --check-prefix=MIPS-EXCLUDE-LLVM %s +# RUN: llvm-readelf -S %t-mips-exclude.o | FileCheck --check-prefix=MIPS-EXCLUDE-GNU %s + +# MIPS-EXCLUDE-LLVM: Name: .mips +# MIPS-EXCLUDE-LLVM-NEXT: Type: SHT_PROGBITS +# MIPS-EXCLUDE-LLVM-NEXT: Flags [ (0x80000000) +# MIPS-EXCLUDE-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# MIPS-EXCLUDE-LLVM-NEXT: SHF_MIPS_STRING (0x80000000) +# MIPS-EXCLUDE-LLVM-NEXT: ] + +# MIPS-EXCLUDE-GNU: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# MIPS-EXCLUDE-GNU: [ 1] .mips PROGBITS 00000000 000034 000000 00 E 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .mips + Type: SHT_PROGBITS + Flags: [ SHF_MIPS_STRING ] + +# RUN: yaml2obj --docnum 4 %s -o %t-x86_64.o # RUN: llvm-readobj -S %t-x86_64.o | FileCheck --check-prefix=X86_64-LLVM %s # RUN: llvm-readelf -S %t-x86_64.o | FileCheck --check-prefix=X86_64-GNU %s @@ -77,7 +103,7 @@ Type: SHT_PROGBITS Flags: [ SHF_X86_64_LARGE ] -# RUN: yaml2obj --docnum 4 %s -o %t-arm.o +# RUN: yaml2obj --docnum 5 %s -o %t-arm.o # RUN: llvm-readobj -S %t-arm.o | FileCheck --check-prefix=ARM-LLVM %s # RUN: llvm-readelf -S %t-arm.o | FileCheck --check-prefix=ARM-GNU %s @@ -98,3 +124,122 @@ - Name: foo Type: SHT_PROGBITS Flags: [ SHF_ARM_PURECODE ] + +## SHF_MASKPROC has a value of 0xf0000000, SHF_EXCLUDE has a value of +## 0x80000000. When SHF_EXCLUDE is mixed with other proccessor specific +## flags, GNU readelf does not necessarily print "E", because it handles +## the SHF_MASKPROC mask first. It only prints "E" when there are no other +## proccessor flags set. Check llvm-readelf output matches GNU. + +# RUN: yaml2obj --docnum 6 %s -o %t6.o +# RUN: llvm-readobj -S %t6.o | FileCheck --check-prefix=OS-PROC-LLVM %s +# RUN: llvm-readelf -S %t6.o | FileCheck --check-prefix=OS-PROC-GNU %s + +# OS-PROC-LLVM: Name: .os.flags.min +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0x100000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .os.flags.max +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xFE00000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .os.flags.mask +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xFF00000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .proc.flags.min +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0x10000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .proc.flags.max +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xE0000000) +# OS-PROC-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .proc.flags.mask +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xF0000000) +# OS-PROC-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .both.flags.mask +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xFFF00000) +# OS-PROC-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .both.flags.minvalues +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0x10100000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .both.flags.maxvalues +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xEFE00000) +# OS-PROC-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .exclude +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0x80000000) +# OS-PROC-LLVM-NEXT: SHF_EXCLUDE (0x80000000) +# OS-PROC-LLVM-NEXT: ] +# OS-PROC-LLVM: Name: .unknown +# OS-PROC-LLVM-NEXT: Type: SHT_PROGBITS +# OS-PROC-LLVM-NEXT: Flags [ (0xF0000) +# OS-PROC-LLVM-NEXT: ] + +# OS-PROC-GNU: Section Headers: +# OS-PROC-GNU-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# OS-PROC-GNU-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 +# OS-PROC-GNU-NEXT: [ 1] .os.flags.min PROGBITS 0000000000000000 000040 000000 00 o 0 0 0 +# OS-PROC-GNU-NEXT: [ 2] .os.flags.max PROGBITS 0000000000000000 000040 000000 00 o 0 0 0 +# OS-PROC-GNU-NEXT: [ 3] .os.flags.mask PROGBITS 0000000000000000 000040 000000 00 o 0 0 0 +# OS-PROC-GNU-NEXT: [ 4] .proc.flags.min PROGBITS 0000000000000000 000040 000000 00 p 0 0 0 +# OS-PROC-GNU-NEXT: [ 5] .proc.flags.max PROGBITS 0000000000000000 000040 000000 00 p 0 0 0 +# OS-PROC-GNU-NEXT: [ 6] .proc.flags.mask PROGBITS 0000000000000000 000040 000000 00 p 0 0 0 +# OS-PROC-GNU-NEXT: [ 7] .both.flags.mask PROGBITS 0000000000000000 000040 000000 00 op 0 0 0 +# OS-PROC-GNU-NEXT: [ 8] .both.flags.minvalues PROGBITS 0000000000000000 000040 000000 00 op 0 0 0 +# OS-PROC-GNU-NEXT: [ 9] .both.flags.maxvalues PROGBITS 0000000000000000 000040 000000 00 op 0 0 0 +# OS-PROC-GNU-NEXT: [10] .exclude PROGBITS 0000000000000000 000040 000000 00 E 0 0 0 +# OS-PROC-GNU-NEXT: [11] .unknown PROGBITS 0000000000000000 000040 000000 00 x 0 0 0 + +## Use an arbitraty EM_* machine type that does not have specific SHF_* OS/Processor +## flags to test what we dump when bits in the OS and processor specific ranges are set. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .os.flags.min + Type: SHT_PROGBITS + ShFlags: 0x00100000 + - Name: .os.flags.max + Type: SHT_PROGBITS + ShFlags: 0x0FE00000 + - Name: .os.flags.mask + Type: SHT_PROGBITS + ShFlags: 0x0FF00000 + - Name: .proc.flags.min + Type: SHT_PROGBITS + ShFlags: 0x10000000 + - Name: .proc.flags.max + Type: SHT_PROGBITS + ShFlags: 0xE0000000 + - Name: .proc.flags.mask + Type: SHT_PROGBITS + ShFlags: 0xF0000000 + - Name: .both.flags.mask + Type: SHT_PROGBITS + ShFlags: 0xFFF00000 + - Name: .both.flags.minvalues + Type: SHT_PROGBITS + ShFlags: 0x10100000 + - Name: .both.flags.maxvalues + Type: SHT_PROGBITS + ShFlags: 0xEFE00000 + - Name: .exclude + Type: SHT_PROGBITS + ShFlags: 0x80000000 + - Name: .unknown + Type: SHT_PROGBITS + ShFlags: 0x000f0000 Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1444,8 +1444,6 @@ ENUM_ENT(SHF_TLS, "T"), ENUM_ENT(SHF_COMPRESSED, "C"), ENUM_ENT(SHF_EXCLUDE, "E"), - ENUM_ENT(SHF_MASKOS, "o"), - ENUM_ENT(SHF_MASKPROC, "p"), }; static const EnumEntry ElfXCoreSectionFlags[] = { @@ -1477,34 +1475,51 @@ }; static std::string getGNUFlags(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. + // GNU readelf will not print "E" or "Ep" in this case, but will print just + // "p". It only will print "E" when no other processor flag is set. std::string Str; - for (auto Entry : ElfSectionFlags) { - uint64_t Flag = Entry.Value & Flags; - Flags &= ~Entry.Value; - switch (Flag) { - case ELF::SHF_WRITE: - case ELF::SHF_ALLOC: - case ELF::SHF_EXECINSTR: - case ELF::SHF_MERGE: - case ELF::SHF_STRINGS: - case ELF::SHF_INFO_LINK: - case ELF::SHF_LINK_ORDER: - case ELF::SHF_OS_NONCONFORMING: - case ELF::SHF_GROUP: - case ELF::SHF_TLS: - case ELF::SHF_COMPRESSED: - case ELF::SHF_EXCLUDE: - Str += Entry.AltName; - break; - default: - if (Flag & ELF::SHF_MASKOS) - Str += "o"; - else if (Flag & ELF::SHF_MASKPROC) - Str += "p"; - else if (Flag) - Str += "x"; + bool HasUnknownFlag = false; + bool HasOSFlag = false; + bool HasProcFlag = false; + while (Flags) { + // Take the least significant bit as a flag. + uint64_t Flag = Flags & -Flags; + Flags &= ~Flag; + + // Find the flag in the known flags list. + auto I = llvm::find_if(ElfSectionFlags, [=](const EnumEntry &E) { + return E.Value == Flag; + }); + if (I != std::end(ElfSectionFlags)) { + Str += I->AltName; + continue; + } + + // If we did not find a matching regular flag, then we deal with an OS + // specific flag, proccessor specific flag or an unknown flag. + if (Flag & ELF::SHF_MASKOS) { + HasOSFlag = true; + Flags &= ~ELF::SHF_MASKOS; + } else if (Flag & ELF::SHF_MASKPROC) { + HasProcFlag = true; + // Mask off all the processor-specific bits. This removes the SHF_EXCLUDE + // bit if set so that it doesn't also get printed. + Flags &= ~ELF::SHF_MASKPROC; + } else { + HasUnknownFlag = true; } } + + // "o", "p" and "x" are printed last. + if (HasOSFlag) + Str += "o"; + if (HasProcFlag) + Str += "p"; + if (HasUnknownFlag) + Str += "x"; return Str; }