diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def --- a/llvm/include/llvm/BinaryFormat/DynamicTags.def +++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -120,6 +120,7 @@ // AArch64 specific dynamic table entries AARCH64_DYNAMIC_TAG(AARCH64_BTI_PLT, 0x70000001) AARCH64_DYNAMIC_TAG(AARCH64_PAC_PLT, 0x70000003) +AARCH64_DYNAMIC_TAG(AARCH64_VARIANT_PCS, 0x70000005) // Hexagon specific dynamic table entries HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000) diff --git a/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test b/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test @@ -0,0 +1,45 @@ +## Check that we are able to dump AArch64 STO_* flags correctly when dumping symbols. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-readobj --symbols %t.o | FileCheck %s --check-prefix=LLVM +# RUN: llvm-readelf --symbols %t.o | FileCheck %s --check-prefix=GNU + +# LLVM: Name: foo1 +# LLVM: Other [ (0x80) +# LLVM-NEXT: STO_AARCH64_VARIANT_PCS (0x80) +# LLVM-NEXT: ] +# LLVM: Name: foo2 +# LLVM: Other [ (0xC0) +# LLVM-NEXT: STO_AARCH64_VARIANT_PCS (0x80) +# LLVM-NEXT: ] +# LLVM: Name: foo3 +# LLVM: Other [ (0x83) +# LLVM-NEXT: STO_AARCH64_VARIANT_PCS (0x80) +# LLVM-NEXT: STV_PROTECTED (0x3) +# LLVM-NEXT: ] +# LLVM: Name: foo4 +# LLVM: Other [ (0x3) +# LLVM-NEXT: STV_PROTECTED (0x3) +# LLVM-NEXT: ] + +# GNU: Symbol table '.symtab' contains 5 entries: +# GNU: 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_PCS] UND foo1 +# GNU-NEXT: 2: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_PCS | 40] UND foo2 +# GNU-NEXT: 3: 0000000000000000 0 NOTYPE LOCAL PROTECTED [VARIANT_PCS] UND foo3 +# GNU-NEXT: 4: 0000000000000000 0 NOTYPE LOCAL PROTECTED UND foo4 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_AARCH64 +Symbols: + - Name: foo1 + Other: [ STO_AARCH64_VARIANT_PCS ] + - Name: foo2 + Other: [ STO_AARCH64_VARIANT_PCS, 0x40 ] + - Name: foo3 + Other: [ STO_AARCH64_VARIANT_PCS, STV_PROTECTED ] + - Name: foo4 + Other: [ STV_PROTECTED ] diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test --- a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test +++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test @@ -351,18 +351,20 @@ # RUN: llvm-readobj --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=LLVM-AARCH64 # RUN: llvm-readelf --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=GNU-AARCH64 -# LLVM-AARCH64: DynamicSection [ (3 entries) -# LLVM-AARCH64-NEXT: Tag Type Name/Value -# LLVM-AARCH64-NEXT: 0x0000000070000001 AARCH64_BTI_PLT 1 -# LLVM-AARCH64-NEXT: 0x0000000070000003 AARCH64_PAC_PLT 2 -# LLVM-AARCH64-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-AARCH64: DynamicSection [ (4 entries) +# LLVM-AARCH64-NEXT: Tag Type Name/Value +# LLVM-AARCH64-NEXT: 0x0000000070000001 AARCH64_BTI_PLT 1 +# LLVM-AARCH64-NEXT: 0x0000000070000003 AARCH64_PAC_PLT 2 +# LLVM-AARCH64-NEXT: 0x0000000070000005 AARCH64_VARIANT_PCS 3 +# LLVM-AARCH64-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-AARCH64-NEXT:] -# GNU-AARCH64: Dynamic section at offset {{.*}} contains 3 entries: -# GNU-AARCH64-NEXT: Tag Type Name/Value -# GNU-AARCH64-NEXT: 0x0000000070000001 (AARCH64_BTI_PLT) 1 -# GNU-AARCH64-NEXT: 0x0000000070000003 (AARCH64_PAC_PLT) 2 -# GNU-AARCH64-NEXT: 0x0000000000000000 (NULL) 0x0 +# GNU-AARCH64: Dynamic section at offset {{.*}} contains 4 entries: +# GNU-AARCH64-NEXT: Tag Type Name/Value +# GNU-AARCH64-NEXT: 0x0000000070000001 (AARCH64_BTI_PLT) 1 +# GNU-AARCH64-NEXT: 0x0000000070000003 (AARCH64_PAC_PLT) 2 +# GNU-AARCH64-NEXT: 0x0000000070000005 (AARCH64_VARIANT_PCS) 3 +# GNU-AARCH64-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: @@ -378,6 +380,8 @@ Value: 1 - Tag: DT_AARCH64_PAC_PLT Value: 2 + - Tag: DT_AARCH64_VARIANT_PCS + Value: 3 - Tag: DT_NULL Value: 0 ProgramHeaders: 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 @@ -1844,6 +1844,10 @@ LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS) }; +static const EnumEntry ElfAArch64SymOtherFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS) +}; + static const EnumEntry ElfMips16SymOtherFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), @@ -2474,6 +2478,7 @@ switch (Type) { case DT_AARCH64_BTI_PLT: case DT_AARCH64_PAC_PLT: + case DT_AARCH64_VARIANT_PCS: return std::to_string(Value); default: break; @@ -4049,9 +4054,22 @@ printEnum(Symbol.getBinding(), makeArrayRef(ElfSymbolBindings)); Fields[5].Str = printEnum(Symbol.getVisibility(), makeArrayRef(ElfSymbolVisibilities)); - if (Symbol.st_other & ~0x3) - Fields[5].Str += - " []"; + + if (Symbol.st_other & ~0x3) { + if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) { + uint8_t Other = Symbol.st_other & ~0x3; + if (Other & STO_AARCH64_VARIANT_PCS) { + Other &= ~STO_AARCH64_VARIANT_PCS; + Fields[5].Str += " [VARIANT_PCS"; + if (Other != 0) + Fields[5].Str.append(" | " + to_hexString(Other, false)); + Fields[5].Str.append("]"); + } + } else { + Fields[5].Str += + " []"; + } + } Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0; Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex); @@ -6583,6 +6601,10 @@ SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfMipsSymOtherFlags), std::end(ElfMipsSymOtherFlags)); + } else if (this->Obj.getHeader().e_machine == EM_AARCH64) { + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfAArch64SymOtherFlags), + std::end(ElfAArch64SymOtherFlags)); } W.printFlags("Other", Symbol.st_other, makeArrayRef(SymOtherFlags), 0x3u); }