diff options
Diffstat (limited to 'llvm/tools/llvm-readobj/ELFDumper.cpp')
-rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 127 |
1 files changed, 71 insertions, 56 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 4b406ef12aec..d3534820c117 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -61,6 +61,7 @@ #include "llvm/Support/SystemZ/zOSSupport.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <array> #include <cinttypes> #include <cstddef> #include <cstdint> @@ -5105,6 +5106,73 @@ template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() { } } +template <class ELFT> +static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize, + ArrayRef<uint8_t> Desc) { + OS << " AArch64 PAuth ABI core info: "; + // DataSize - size without padding, Desc.size() - size with padding + if (DataSize != 16) { + OS << format("<corrupted size: expected 16, got %d>", DataSize); + return false; + } + + uint64_t Platform = + support::endian::read64<ELFT::Endianness>(Desc.data() + 0); + uint64_t Version = support::endian::read64<ELFT::Endianness>(Desc.data() + 8); + + const char *PlatformDesc = [Platform]() { + switch (Platform) { + case AARCH64_PAUTH_PLATFORM_INVALID: + return "invalid"; + case AARCH64_PAUTH_PLATFORM_BAREMETAL: + return "baremetal"; + case AARCH64_PAUTH_PLATFORM_LLVM_LINUX: + return "llvm_linux"; + default: + return "unknown"; + } + }(); + + std::string VersionDesc = [Platform, Version]() -> std::string { + if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX) + return ""; + if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1))) + return "unknown"; + + std::array<StringRef, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1> + Flags; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS] = "Intrinsics"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS] = "Calls"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS] = "Returns"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS] = "AuthTraps"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR] = + "VTPtrAddressDiscrimination"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] = + "VTPtrTypeDiscrimination"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini"; + + static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI == + AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, + "Update when new enum items are defined"); + + std::string Desc; + for (uint32_t I = 0, End = Flags.size(); I < End; ++I) { + if (!(Version & (1ULL << I))) + Desc += '!'; + Desc += + Twine("PointerAuth" + Flags[I] + (I == End - 1 ? "" : ", ")).str(); + } + return Desc; + }(); + + OS << format("platform 0x%" PRIx64 " (%s), version 0x%" PRIx64, Platform, + PlatformDesc, Version); + if (!VersionDesc.empty()) + OS << format(" (%s)", VersionDesc.c_str()); + + return true; +} + template <typename ELFT> static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, ArrayRef<uint8_t> Data) { @@ -5162,6 +5230,9 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, if (PrData) OS << format("<unknown flags: 0x%x>", PrData); return OS.str(); + case GNU_PROPERTY_AARCH64_FEATURE_PAUTH: + printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data); + return OS.str(); case GNU_PROPERTY_X86_FEATURE_2_NEEDED: case GNU_PROPERTY_X86_FEATURE_2_USED: OS << "x86 feature " @@ -5364,29 +5435,6 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType, } template <class ELFT> -static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType, - ArrayRef<uint8_t> Desc) { - if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG) - return false; - - OS << " AArch64 PAuth ABI tag: "; - if (Desc.size() < 16) { - OS << format("<corrupted size: expected at least 16, got %d>", Desc.size()); - return false; - } - - uint64_t Platform = endian::read64<ELFT::Endianness>(Desc.data() + 0); - uint64_t Version = endian::read64<ELFT::Endianness>(Desc.data() + 8); - OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version); - - if (Desc.size() > 16) - OS << ", additional info 0x" - << toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16)); - - return true; -} - -template <class ELFT> void GNUELFDumper<ELFT>::printMemtag( const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, const ArrayRef<uint8_t> AndroidNoteDesc, @@ -5783,10 +5831,6 @@ const NoteType AndroidNoteTypes[] = { "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"}, }; -const NoteType ARMNoteTypes[] = { - {ELF::NT_ARM_TYPE_PAUTH_ABI_TAG, "NT_ARM_TYPE_PAUTH_ABI_TAG"}, -}; - const NoteType CoreNoteTypes[] = { {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"}, {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"}, @@ -5905,8 +5949,6 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) { return FindNote(LLVMOMPOFFLOADNoteTypes); if (Name == "Android") return FindNote(AndroidNoteTypes); - if (Name == "ARM") - return FindNote(ARMNoteTypes); if (ELFType == ELF::ET_CORE) return FindNote(CoreNoteTypes); @@ -6062,9 +6104,6 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() { } else if (Name == "Android") { if (printAndroidNote(OS, Type, Descriptor)) return Error::success(); - } else if (Name == "ARM") { - if (printAArch64Note<ELFT>(OS, Type, Descriptor)) - return Error::success(); } if (!Descriptor.empty()) { OS << " description data:"; @@ -7703,27 +7742,6 @@ static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, } template <class ELFT> -static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, - ScopedPrinter &W) { - if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG) - return false; - - if (Desc.size() < 16) - return false; - - uint64_t platform = endian::read64<ELFT::Endianness>(Desc.data() + 0); - uint64_t version = endian::read64<ELFT::Endianness>(Desc.data() + 8); - W.printNumber("Platform", platform); - W.printNumber("Version", version); - - if (Desc.size() > 16) - W.printString("Additional info", - toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16))); - - return true; -} - -template <class ELFT> void LLVMELFDumper<ELFT>::printMemtag( const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, const ArrayRef<uint8_t> AndroidNoteDesc, @@ -7859,9 +7877,6 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() { } else if (Name == "Android") { if (printAndroidNoteLLVMStyle(Type, Descriptor, W)) return Error::success(); - } else if (Name == "ARM") { - if (printAarch64NoteLLVMStyle<ELFT>(Type, Descriptor, W)) - return Error::success(); } if (!Descriptor.empty()) { W.printBinaryBlock("Description data", Descriptor); |