From 8971b99c8387f3daf2e802956f2688b3b77335a4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 29 Sep 2021 16:56:52 -0700 Subject: [PATCH] [llvm-objdump/llvm-readobj/obj2yaml/yaml2obj] Support STO_RISCV_VARIANT_CC and DT_RISCV_VARIANT_CC STO_RISCV_VARIANT_CC marks that a symbol uses a non-standard calling convention or the vector calling convention. See https://github.com/riscv/riscv-elf-psabi-doc/pull/190 Differential Revision: https://reviews.llvm.org/D107949 --- llvm/include/llvm/BinaryFormat/DynamicTags.def | 12 +++++++ llvm/include/llvm/BinaryFormat/ELF.h | 6 ++++ llvm/lib/Object/ELF.cpp | 10 ++++++ llvm/lib/ObjectYAML/ELFYAML.cpp | 9 +++++ .../ELF/dynamic-section-machine-specific.test | 29 +++++++++++++++++ .../test/tools/llvm-readobj/ELF/RISCV/stother.test | 38 ++++++++++++++++++++++ .../ELF/dynamic-tags-machine-specific.test | 38 ++++++++++++++++++++++ .../obj2yaml/ELF/dynamic-section-arch-tags.yaml | 22 ++++++++++++- llvm/test/tools/obj2yaml/ELF/riscv-sym-other.yaml | 22 +++++++++++++ llvm/tools/llvm-readobj/ELFDumper.cpp | 16 +++++++++ 10 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-readobj/ELF/RISCV/stother.test create mode 100644 llvm/test/tools/obj2yaml/ELF/riscv-sym-other.yaml diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def index c08f8a5..814d8b1 100644 --- a/llvm/include/llvm/BinaryFormat/DynamicTags.def +++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -31,6 +31,11 @@ #define PPC64_DYNAMIC_TAG_DEFINED #endif +#ifndef RISCV_DYNAMIC_TAG +#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define RISCV_DYNAMIC_TAG_DEFINED +#endif + #ifndef DYNAMIC_TAG_MARKER #define DYNAMIC_TAG_MARKER(name, value) DYNAMIC_TAG(name, value) #define DYNAMIC_TAG_MARKER_DEFINED @@ -213,6 +218,9 @@ PPC_DYNAMIC_TAG(PPC_OPT, 0x70000001) // Has TLS optimization. PPC64_DYNAMIC_TAG(PPC64_GLINK, 0x70000000) // Address of 32 bytes before the // first glink lazy resolver stub. +// RISC-V specific dynamic array tags. +RISCV_DYNAMIC_TAG(RISCV_VARIANT_CC, 0x70000001) + // Sun machine-independent extensions. DYNAMIC_TAG(AUXILIARY, 0x7FFFFFFD) // Shared object to load before self DYNAMIC_TAG(USED, 0x7FFFFFFE) // Same as DT_NEEDED @@ -243,3 +251,7 @@ DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from #undef PPC64_DYNAMIC_TAG #undef PPC64_DYNAMIC_TAG_DEFINED #endif +#ifdef RISCV_DYNAMIC_TAG_DEFINED +#undef RISCV_DYNAMIC_TAG +#undef RISCV_DYNAMIC_TAG_DEFINED +#endif diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 540675d..df9fd49 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -660,6 +660,12 @@ enum { #include "ELFRelocs/RISCV.def" }; +enum { + // Symbol may follow different calling convention than the standard calling + // convention. + STO_RISCV_VARIANT_CC = 0x80 +}; + // ELF Relocation types for S390/zSeries enum { #include "ELFRelocs/SystemZ.def" diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index e9bf482..cd9f881 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -492,6 +492,14 @@ std::string ELFFile::getDynamicTagAsString(unsigned Arch, #undef PPC64_DYNAMIC_TAG } break; + + case ELF::EM_RISCV: + switch (Type) { +#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef RISCV_DYNAMIC_TAG + } + break; } #undef DYNAMIC_TAG switch (Type) { @@ -501,6 +509,7 @@ std::string ELFFile::getDynamicTagAsString(unsigned Arch, #define HEXAGON_DYNAMIC_TAG(name, value) #define PPC_DYNAMIC_TAG(name, value) #define PPC64_DYNAMIC_TAG(name, value) +#define RISCV_DYNAMIC_TAG(name, value) // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. #define DYNAMIC_TAG_MARKER(name, value) #define DYNAMIC_TAG(name, value) case value: return #name; @@ -511,6 +520,7 @@ std::string ELFFile::getDynamicTagAsString(unsigned Arch, #undef HEXAGON_DYNAMIC_TAG #undef PPC_DYNAMIC_TAG #undef PPC64_DYNAMIC_TAG +#undef RISCV_DYNAMIC_TAG #undef DYNAMIC_TAG_MARKER #undef DYNAMIC_STRINGIFY_ENUM default: diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 3edf500..a9e63a6 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -890,6 +890,13 @@ void ScalarEnumerationTraits::enumeration( #undef PPC64_DYNAMIC_TAG #define PPC64_DYNAMIC_TAG(name, value) break; + case ELF::EM_RISCV: +#undef RISCV_DYNAMIC_TAG +#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef RISCV_DYNAMIC_TAG +#define RISCV_DYNAMIC_TAG(name, value) + break; default: #include "llvm/BinaryFormat/DynamicTags.def" break; @@ -1168,6 +1175,8 @@ struct NormalizedOther { if (EMachine == ELF::EM_AARCH64) Map["STO_AARCH64_VARIANT_PCS"] = ELF::STO_AARCH64_VARIANT_PCS; + if (EMachine == ELF::EM_RISCV) + Map["STO_RISCV_VARIANT_CC"] = ELF::STO_RISCV_VARIANT_CC; return Map; } diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test index 2f3b7cb1..08d7d2e 100644 --- a/llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test +++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test @@ -289,3 +289,32 @@ ProgramHeaders: - Type: PT_DYNAMIC FirstSec: .dynamic LastSec: .dynamic + +## Case 6: Test that RISC-V machine-specific tags can be dumped. +# RUN: yaml2obj --docnum=6 %s -o %t.rv +# RUN: llvm-objdump -p %t.rv | FileCheck %s --check-prefix=RISCV + +# RISCV: Dynamic Section: +# RISCV-NEXT: RISCV_VARIANT_CC 0x0000000000000001 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_RISCV +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RISCV_VARIANT_CC + Value: 1 + - Tag: DT_NULL + Value: 0 +ProgramHeaders: + - Type: PT_LOAD + FirstSec: .dynamic + LastSec: .dynamic + - Type: PT_DYNAMIC + FirstSec: .dynamic + LastSec: .dynamic diff --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/stother.test b/llvm/test/tools/llvm-readobj/ELF/RISCV/stother.test new file mode 100644 index 0000000..b325aeb --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/stother.test @@ -0,0 +1,38 @@ +## Check that we are able to dump RISC-V STO_* flags correctly when dumping symbols. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-readobj -s %t.o | FileCheck %s --check-prefix=LLVM +# RUN: llvm-readelf -s %t.o | FileCheck %s --check-prefix=GNU + +# LLVM: Name: foo1 +# LLVM: Other [ (0x80) +# LLVM-NEXT: STO_RISCV_VARIANT_CC (0x80) +# LLVM-NEXT: ] +# LLVM: Name: foo2 +# LLVM: Other [ (0xC0) +# LLVM-NEXT: STO_RISCV_VARIANT_CC (0x80) +# LLVM-NEXT: ] +# LLVM: Name: foo3 +# LLVM: Other [ (0x83) +# LLVM-NEXT: STO_RISCV_VARIANT_CC (0x80) +# LLVM-NEXT: STV_PROTECTED (0x3) +# LLVM-NEXT: ] + +# GNU: Symbol table '.symtab' contains 4 entries: +# GNU: 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_CC] UND foo1 +# GNU-NEXT: 2: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_CC | 40] UND foo2 +# GNU-NEXT: 3: 0000000000000000 0 NOTYPE LOCAL PROTECTED [VARIANT_CC] UND foo3 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV +Symbols: + - Name: foo1 + Other: [ STO_RISCV_VARIANT_CC ] + - Name: foo2 + Other: [ STO_RISCV_VARIANT_CC, 0x40 ] + - Name: foo3 + Other: [ STO_RISCV_VARIANT_CC, 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 index 02309e5..970edcc 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test +++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test @@ -391,3 +391,41 @@ ProgramHeaders: - Type: PT_DYNAMIC FirstSec: .dynamic LastSec: .dynamic + +## Case 6: Test that RISC-V machine-specific tags can be dumped. +# RUN: yaml2obj --docnum=6 %s -o %t.rv +# RUN: llvm-readobj --dynamic-table %t.rv | FileCheck %s --check-prefix=LLVM-RISCV +# RUN: llvm-readelf --dynamic-table %t.rv | FileCheck %s --check-prefix=GNU-RISCV + +# LLVM-RISCV: DynamicSection [ (2 entries) +# LLVM-RISCV-NEXT: Tag Type Name/Value +# LLVM-RISCV-NEXT: 0x0000000070000001 RISCV_VARIANT_CC 0x1 +# LLVM-RISCV-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-RISCV-NEXT: ] + +# GNU-RISCV: Dynamic section at offset {{.*}} contains 2 entries: +# GNU-RISCV-NEXT: Tag Type Name/Value +# GNU-RISCV-NEXT: 0x0000000070000001 (RISCV_VARIANT_CC) 0x1 +# GNU-RISCV-NEXT: 0x0000000000000000 (NULL) 0x0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_RISCV +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RISCV_VARIANT_CC + Value: 1 + - Tag: DT_NULL + Value: 0 +ProgramHeaders: + - Type: PT_LOAD + FirstSec: .dynamic + LastSec: .dynamic + - Type: PT_DYNAMIC + FirstSec: .dynamic + LastSec: .dynamic diff --git a/llvm/test/tools/obj2yaml/ELF/dynamic-section-arch-tags.yaml b/llvm/test/tools/obj2yaml/ELF/dynamic-section-arch-tags.yaml index cf08db8..5523b2f 100644 --- a/llvm/test/tools/obj2yaml/ELF/dynamic-section-arch-tags.yaml +++ b/llvm/test/tools/obj2yaml/ELF/dynamic-section-arch-tags.yaml @@ -297,12 +297,32 @@ Sections: - Tag: DT_AARCH64_PAC_PLT Value: 0x0000000000000000 +## Check we can handle RISC-V specific tags. +# RUN: yaml2obj --docnum=6 %s -o %t6 +# RUN: obj2yaml %t6 | FileCheck %s --check-prefix=RISCV + +# RISCV: - Tag: DT_RISCV_VARIANT_CC +# RISCV-NEXT: Value: 0x0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RISCV_VARIANT_CC + Value: 0x0000000000000000 + ## Check we can't use a tag from a different architecture, ## even if it has the same numeric value as a valid tag. ## Here for EM_PPC64 we are trying to use DT_HEXAGON_SYMSZ ## instead of DT_PPC64_GLINK. They both have value of 0x70000000. -# RUN: not yaml2obj --docnum=6 %s 2>&1 | FileCheck %s --check-prefix=ERR +# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=ERR # ERR: error: invalid hex64 number # ERR-NEXT: - Tag: DT_HEXAGON_SYMSZ diff --git a/llvm/test/tools/obj2yaml/ELF/riscv-sym-other.yaml b/llvm/test/tools/obj2yaml/ELF/riscv-sym-other.yaml new file mode 100644 index 0000000..0172c3a --- /dev/null +++ b/llvm/test/tools/obj2yaml/ELF/riscv-sym-other.yaml @@ -0,0 +1,22 @@ +## Check RISC-V st_other extension support. + +# RUN: yaml2obj %s -o %t +# RUN: obj2yaml %t | FileCheck %s + +# CHECK: Symbols: +# CHECK: - Name: foo1 +# CHECK: Other: [ STO_RISCV_VARIANT_CC ] +# CHECK: - Name: foo2 +# CHECK: Other: [ STO_RISCV_VARIANT_CC, 64 ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV +Symbols: + - Name: foo1 + Other: [ STO_RISCV_VARIANT_CC ] + - Name: foo2 + Other: [ STO_RISCV_VARIANT_CC, 0x40 ] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 56fd7c7..ff81768 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1616,6 +1616,9 @@ static const EnumEntry ElfMips16SymOtherFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16) }; +static const EnumEntry ElfRISCVSymOtherFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)}; + static const char *getElfMipsOptionsOdkType(unsigned Odk) { switch (Odk) { LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL); @@ -3773,6 +3776,15 @@ void GNUELFDumper::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, Fields[5].Str.append(" | " + to_hexString(Other, false)); Fields[5].Str.append("]"); } + } else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) { + uint8_t Other = Symbol.st_other & ~0x3; + if (Other & STO_RISCV_VARIANT_CC) { + Other &= ~STO_RISCV_VARIANT_CC; + Fields[5].Str += " [VARIANT_CC"; + if (Other != 0) + Fields[5].Str.append(" | " + to_hexString(Other, false)); + Fields[5].Str.append("]"); + } } else { Fields[5].Str += " []"; @@ -6577,6 +6589,10 @@ void LLVMELFDumper::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfAArch64SymOtherFlags), std::end(ElfAArch64SymOtherFlags)); + } else if (this->Obj.getHeader().e_machine == EM_RISCV) { + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfRISCVSymOtherFlags), + std::end(ElfRISCVSymOtherFlags)); } W.printFlags("Other", Symbol.st_other, makeArrayRef(SymOtherFlags), 0x3u); } -- 2.7.4