Index: lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h =================================================================== --- lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h +++ lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h @@ -22,6 +22,7 @@ #include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm/MC/MCDisassembler/MCSymbolizer.h" +#include "llvm/Object/ELFNoteDumper.h" #include #include @@ -150,6 +151,24 @@ uint64_t Address) override; }; +//===----------------------------------------------------------------------===// +// AMDGPUELFNoteDumper +//===----------------------------------------------------------------------===// + +class AMDGPUELFNoteDumper : public ELFNoteDumper { +public: + AMDGPUELFNoteDumper() : ELFNoteDumper() {} + + // Dump the contents of one note from the ELF .note section in readable + // format. This returns false if the implementation does not understand the + // note. + // The .note descriptor (i.e. contents) is passed as an StringRef of bytes as + // found in the ELF file, together with an indication of the endianness of + // the ELF file. + virtual bool dumpNote(unsigned Type, StringRef Name, StringRef Desc, + support::endianness TargetEndianness, raw_ostream &OS) override; +}; + } // end namespace llvm #endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H Index: lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp =================================================================== --- lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -21,6 +21,7 @@ #include "AMDGPU.h" #include "AMDGPURegisterInfo.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "SIDefines.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "Utils/AMDGPUBaseInfo.h" @@ -919,6 +920,56 @@ } //===----------------------------------------------------------------------===// +// AMDGPUELFNoteDumper +//===----------------------------------------------------------------------===// + +// Dump the contents of one note from the ELF .note section in readable +// format. This returns false if the implementation does not understand the +// note. +bool AMDGPUELFNoteDumper::dumpNote(unsigned Type, StringRef Name, + StringRef Desc, support::endianness TargetEndianness, raw_ostream &OS) { + if (Name != "AMD") + return false; + switch (Type) { + default: + return false; + case ELF::NT_AMD_AMDGPU_HSA_METADATA: + OS << "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)\n"; + OS << " HSA Metadata:\n" + << Desc; + return true; + case ELF::NT_AMD_AMDGPU_ISA: + OS << "NT_AMD_AMDGPU_ISA (ISA Version)\n"; + OS << " ISA Version:\n" + << " " + << Desc; + return true; + case ELF::NT_AMD_AMDGPU_PAL_METADATA: { + // PAL metadata is in 32-bit words and only exists on AMDGPU, which is + // always little endian, so the following does not work if running + // llvm-readobj on a big-endian host. +#if BYTE_ORDER == LITTLE_ENDIAN + OS << "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)\n"; + const uint32_t *PALMetadataBegin + = reinterpret_cast(Desc.data()); + const uint32_t *PALMetadataEnd + = PALMetadataBegin + Desc.size() / sizeof(uint32_t); + std::vector PALMetadata(PALMetadataBegin, PALMetadataEnd); + std::string PALMetadataString; + auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString); + OS << " PAL Metadata:\n"; + if (Error) + OS << " Invalid"; + else + OS << PALMetadataString; + return true; +#endif + return false; + } + } +} + +//===----------------------------------------------------------------------===// // Initialization //===----------------------------------------------------------------------===// @@ -937,9 +988,15 @@ return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo()); } +static ELFNoteDumper *createAMDGPUELFNoteDumper(const Target &T) { + return new AMDGPUELFNoteDumper(); +} + extern "C" void LLVMInitializeAMDGPUDisassembler() { TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(), createAMDGPUDisassembler); TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(), createAMDGPUSymbolizer); + TargetRegistry::RegisterELFNoteDumper(getTheGCNTarget(), + createAMDGPUELFNoteDumper); } Index: test/CodeGen/AMDGPU/elf-notes.ll =================================================================== --- test/CodeGen/AMDGPU/elf-notes.ll +++ test/CodeGen/AMDGPU/elf-notes.ll @@ -31,8 +31,8 @@ ; OSABI-HSA: .amd_amdgpu_hsa_metadata ; OSABI-HSA-NOT: .amd_amdgpu_pal_metadata -; OSABI-HSA-ELF: Unknown note type (0x00000001) -; OSABI-HSA-ELF: Unknown note type (0x00000003) +; OSABI-HSA-ELF: Unknown note type: (0x00000001) +; OSABI-HSA-ELF: Unknown note type: (0x00000003) ; OSABI-HSA-ELF: NT_AMD_AMDGPU_ISA (ISA Version) ; OSABI-HSA-ELF: ISA Version: ; OSABI-HSA-ELF: amdgcn-amd-amdhsa--gfx802 @@ -59,7 +59,7 @@ ; OSABI-PAL-NOT: .amd_amdgpu_hsa_metadata ; OSABI-PAL: .amd_amdgpu_pal_metadata -; OSABI-PAL-ELF: Unknown note type (0x00000003) +; OSABI-PAL-ELF: Unknown note type: (0x00000003) ; OSABI-PAL-ELF: NT_AMD_AMDGPU_ISA (ISA Version) ; OSABI-PAL-ELF: ISA Version: ; OSABI-PAL-ELF: amdgcn-amd-amdpal--gfx802 Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -3585,29 +3585,6 @@ return OS.str(); } -static std::string getAMDGPUNoteTypeName(const uint32_t NT) { - static const struct { - uint32_t ID; - const char *Name; - } Notes[] = { - {ELF::NT_AMD_AMDGPU_HSA_METADATA, - "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"}, - {ELF::NT_AMD_AMDGPU_ISA, - "NT_AMD_AMDGPU_ISA (ISA Version)"}, - {ELF::NT_AMD_AMDGPU_PAL_METADATA, - "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"} - }; - - for (const auto &Note : Notes) - if (Note.ID == NT) - return std::string(Note.Name); - - std::string string; - raw_string_ostream OS(string); - OS << format("Unknown note type (0x%08x)", NT); - return OS.str(); -} - template static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize, ArrayRef Data) { @@ -3727,38 +3704,6 @@ OS << '\n'; } -template -static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType, - ArrayRef Words, size_t Size) { - switch (NoteType) { - default: - return; - case ELF::NT_AMD_AMDGPU_HSA_METADATA: - OS << " HSA Metadata:\n" - << StringRef(reinterpret_cast(Words.data()), Size); - break; - case ELF::NT_AMD_AMDGPU_ISA: - OS << " ISA Version:\n" - << " " - << StringRef(reinterpret_cast(Words.data()), Size); - break; - case ELF::NT_AMD_AMDGPU_PAL_METADATA: - const uint32_t *PALMetadataBegin = reinterpret_cast(Words.data()); - const uint32_t *PALMetadataEnd = PALMetadataBegin + Size; - std::vector PALMetadata(PALMetadataBegin, PALMetadataEnd); - std::string PALMetadataString; - auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString); - OS << " PAL Metadata:\n"; - if (Error) { - OS << " Invalid"; - return; - } - OS << PALMetadataString; - break; - } - OS.flush(); -} - template void GNUStyle::printNotes(const ELFFile *Obj) { const Elf_Ehdr *e = Obj->getHeader(); @@ -3790,9 +3735,6 @@ printGNUNote(OS, Type, Descriptor, Descriptor.size()); } else if (Name == "FreeBSD") { OS << getFreeBSDNoteTypeName(Type) << '\n'; - } else if (Name == "AMD") { - OS << getAMDGPUNoteTypeName(Type) << '\n'; - printAMDGPUNote(OS, Type, Descriptor, Descriptor.size()); } else { // See if any compiled-in target knows how to dump this note record. A // target's ELFNoteDumper takes the descriptor as a StringRef of bytes