diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-readobj')
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp | 682 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ARMAttributeParser.h | 126 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/COFFDumper.cpp | 687 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/CodeView.h | 54 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ELFDumper.cpp | 335 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/MachODumper.cpp | 20 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ObjDumper.h | 14 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/WasmDumper.cpp | 209 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp | 79 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/llvm-readobj.h | 5 |
11 files changed, 942 insertions, 1271 deletions
diff --git a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp b/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp deleted file mode 100644 index 877dd71..0000000 --- a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp +++ /dev/null @@ -1,682 +0,0 @@ -//===--- ARMAttributeParser.cpp - ARM Attribute Information Printer -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ARMAttributeParser.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/ScopedPrinter.h" - -using namespace llvm; -using namespace llvm::ARMBuildAttrs; - - -static const EnumEntry<unsigned> TagNames[] = { - { "Tag_File", ARMBuildAttrs::File }, - { "Tag_Section", ARMBuildAttrs::Section }, - { "Tag_Symbol", ARMBuildAttrs::Symbol }, -}; - -namespace llvm { -#define ATTRIBUTE_HANDLER(Attr_) \ - { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ } - -const ARMAttributeParser::DisplayHandler -ARMAttributeParser::DisplayRoutines[] = { - { ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::StringAttribute, }, - { ARMBuildAttrs::CPU_name, &ARMAttributeParser::StringAttribute }, - ATTRIBUTE_HANDLER(CPU_arch), - ATTRIBUTE_HANDLER(CPU_arch_profile), - ATTRIBUTE_HANDLER(ARM_ISA_use), - ATTRIBUTE_HANDLER(THUMB_ISA_use), - ATTRIBUTE_HANDLER(FP_arch), - ATTRIBUTE_HANDLER(WMMX_arch), - ATTRIBUTE_HANDLER(Advanced_SIMD_arch), - ATTRIBUTE_HANDLER(PCS_config), - ATTRIBUTE_HANDLER(ABI_PCS_R9_use), - ATTRIBUTE_HANDLER(ABI_PCS_RW_data), - ATTRIBUTE_HANDLER(ABI_PCS_RO_data), - ATTRIBUTE_HANDLER(ABI_PCS_GOT_use), - ATTRIBUTE_HANDLER(ABI_PCS_wchar_t), - ATTRIBUTE_HANDLER(ABI_FP_rounding), - ATTRIBUTE_HANDLER(ABI_FP_denormal), - ATTRIBUTE_HANDLER(ABI_FP_exceptions), - ATTRIBUTE_HANDLER(ABI_FP_user_exceptions), - ATTRIBUTE_HANDLER(ABI_FP_number_model), - ATTRIBUTE_HANDLER(ABI_align_needed), - ATTRIBUTE_HANDLER(ABI_align_preserved), - ATTRIBUTE_HANDLER(ABI_enum_size), - ATTRIBUTE_HANDLER(ABI_HardFP_use), - ATTRIBUTE_HANDLER(ABI_VFP_args), - ATTRIBUTE_HANDLER(ABI_WMMX_args), - ATTRIBUTE_HANDLER(ABI_optimization_goals), - ATTRIBUTE_HANDLER(ABI_FP_optimization_goals), - ATTRIBUTE_HANDLER(compatibility), - ATTRIBUTE_HANDLER(CPU_unaligned_access), - ATTRIBUTE_HANDLER(FP_HP_extension), - ATTRIBUTE_HANDLER(ABI_FP_16bit_format), - ATTRIBUTE_HANDLER(MPextension_use), - ATTRIBUTE_HANDLER(DIV_use), - ATTRIBUTE_HANDLER(DSP_extension), - ATTRIBUTE_HANDLER(T2EE_use), - ATTRIBUTE_HANDLER(Virtualization_use), - ATTRIBUTE_HANDLER(nodefaults) -}; - -#undef ATTRIBUTE_HANDLER - -uint64_t ARMAttributeParser::ParseInteger(const uint8_t *Data, - uint32_t &Offset) { - unsigned Length; - uint64_t Value = decodeULEB128(Data + Offset, &Length); - Offset = Offset + Length; - return Value; -} - -StringRef ARMAttributeParser::ParseString(const uint8_t *Data, - uint32_t &Offset) { - const char *String = reinterpret_cast<const char*>(Data + Offset); - size_t Length = std::strlen(String); - Offset = Offset + Length + 1; - return StringRef(String, Length); -} - -void ARMAttributeParser::IntegerAttribute(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - SW.printNumber(ARMBuildAttrs::AttrTypeAsString(Tag), - ParseInteger(Data, Offset)); -} - -void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false); - - DictScope AS(SW, "Attribute"); - SW.printNumber("Tag", Tag); - if (!TagName.empty()) - SW.printString("TagName", TagName); - SW.printString("Value", ParseString(Data, Offset)); -} - -void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value, - StringRef ValueDesc) { - StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false); - - DictScope AS(SW, "Attribute"); - SW.printNumber("Tag", Tag); - SW.printNumber("Value", Value); - if (!TagName.empty()) - SW.printString("TagName", TagName); - if (!ValueDesc.empty()) - SW.printString("Description", ValueDesc); -} - -void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6", - "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M", - "ARM v7E-M", "ARM v8" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - uint64_t Encoded = ParseInteger(Data, Offset); - - StringRef Profile; - switch (Encoded) { - default: Profile = "Unknown"; break; - case 'A': Profile = "Application"; break; - case 'R': Profile = "Real-time"; break; - case 'M': Profile = "Microcontroller"; break; - case 'S': Profile = "Classic"; break; - case 0: Profile = "None"; break; - } - - PrintAttribute(Tag, Encoded, Profile); -} - -void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "Permitted" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", - "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON", "ARMv8.1-a NEON" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004", - "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "v6", "Static Base", "TLS", "Unused" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Absolute", "PC-relative", "SB-relative", "Not Permitted" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Absolute", "PC-relative", "Not Permitted" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "Direct", "GOT-Indirect" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "IEEE-754", "Runtime" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Unsupported", "IEEE-754", "Sign Only" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag, - const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "Finite Only", "RTABI", "IEEE-754" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved" - }; - - uint64_t Value = ParseInteger(Data, Offset); - - std::string Description; - if (Value < array_lengthof(Strings)) - Description = std::string(Strings[Value]); - else if (Value <= 12) - Description = std::string("8-byte alignment, ") + utostr(1ULL << Value) - + std::string("-byte extended alignment"); - else - Description = "Invalid"; - - PrintAttribute(Tag, Value, Description); -} - -void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Required", "8-byte data alignment", "8-byte data and code alignment", - "Reserved" - }; - - uint64_t Value = ParseInteger(Data, Offset); - - std::string Description; - if (Value < array_lengthof(Strings)) - Description = std::string(Strings[Value]); - else if (Value <= 12) - Description = std::string("8-byte stack alignment, ") + - utostr(1ULL << Value) + std::string("-byte data alignment"); - else - Description = "Invalid"; - - PrintAttribute(Tag, Value, Description); -} - -void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "Packed", "Int32", "External Int32" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "AAPCS", "AAPCS VFP", "Custom", "Not Permitted" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "AAPCS", "iWMMX", "Custom" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_optimization_goals(AttrType Tag, - const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging", - "Best Debugging" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag, - const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy", - "Best Accuracy" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - uint64_t Integer = ParseInteger(Data, Offset); - StringRef String = ParseString(Data, Offset); - - DictScope AS(SW, "Attribute"); - SW.printNumber("Tag", Tag); - SW.startLine() << "Value: " << Integer << ", " << String << '\n'; - SW.printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false)); - switch (Integer) { - case 0: - SW.printString("Description", StringRef("No Specific Requirements")); - break; - case 1: - SW.printString("Description", StringRef("AEABI Conformant")); - break; - default: - SW.printString("Description", StringRef("AEABI Non-Conformant")); - break; - } -} - -void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "v6-style" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "If Available", "Permitted" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "Permitted" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "If Available", "Not Permitted", "Permitted" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::DSP_extension(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "Permitted" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { "Not Permitted", "Permitted" }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - static const char *const Strings[] = { - "Not Permitted", "TrustZone", "Virtualization Extensions", - "TrustZone + Virtualization Extensions" - }; - - uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = - (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; - PrintAttribute(Tag, Value, ValueDesc); -} - -void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data, - uint32_t &Offset) { - uint64_t Value = ParseInteger(Data, Offset); - PrintAttribute(Tag, Value, "Unspecified Tags UNDEFINED"); -} - -void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset, - SmallVectorImpl<uint8_t> &IndexList) { - for (;;) { - unsigned Length; - uint64_t Value = decodeULEB128(Data + Offset, &Length); - Offset = Offset + Length; - if (Value == 0) - break; - IndexList.push_back(Value); - } -} - -void ARMAttributeParser::ParseAttributeList(const uint8_t *Data, - uint32_t &Offset, uint32_t Length) { - while (Offset < Length) { - unsigned Length; - uint64_t Tag = decodeULEB128(Data + Offset, &Length); - Offset += Length; - - bool Handled = false; - for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines); - AHI != AHE && !Handled; ++AHI) { - if (DisplayRoutines[AHI].Attribute == Tag) { - (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag), - Data, Offset); - Handled = true; - break; - } - } - if (!Handled) { - if (Tag < 32) { - errs() << "unhandled AEABI Tag " << Tag - << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n"; - continue; - } - - if (Tag % 2 == 0) - IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); - else - StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); - } - } -} - -void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) { - uint32_t Offset = sizeof(uint32_t); /* SectionLength */ - - SW.printNumber("SectionLength", Length); - - const char *VendorName = reinterpret_cast<const char*>(Data + Offset); - size_t VendorNameLength = std::strlen(VendorName); - SW.printString("Vendor", StringRef(VendorName, VendorNameLength)); - Offset = Offset + VendorNameLength + 1; - - if (StringRef(VendorName, VendorNameLength).lower() != "aeabi") - return; - - while (Offset < Length) { - /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size - uint8_t Tag = Data[Offset]; - SW.printEnum("Tag", Tag, makeArrayRef(TagNames)); - Offset = Offset + sizeof(Tag); - - uint32_t Size = - *reinterpret_cast<const support::ulittle32_t*>(Data + Offset); - SW.printNumber("Size", Size); - Offset = Offset + sizeof(Size); - - if (Size > Length) { - errs() << "subsection length greater than section length\n"; - return; - } - - StringRef ScopeName, IndexName; - SmallVector<uint8_t, 8> Indicies; - switch (Tag) { - case ARMBuildAttrs::File: - ScopeName = "FileAttributes"; - break; - case ARMBuildAttrs::Section: - ScopeName = "SectionAttributes"; - IndexName = "Sections"; - ParseIndexList(Data, Offset, Indicies); - break; - case ARMBuildAttrs::Symbol: - ScopeName = "SymbolAttributes"; - IndexName = "Symbols"; - ParseIndexList(Data, Offset, Indicies); - break; - default: - errs() << "unrecognised tag: 0x" << utohexstr(Tag) << '\n'; - return; - } - - DictScope ASS(SW, ScopeName); - - if (!Indicies.empty()) - SW.printList(IndexName, Indicies); - - ParseAttributeList(Data, Offset, Length); - } -} - -void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section) { - size_t Offset = 1; - unsigned SectionNumber = 0; - - while (Offset < Section.size()) { - uint32_t SectionLength = - *reinterpret_cast<const support::ulittle32_t*>(Section.data() + Offset); - - SW.startLine() << "Section " << ++SectionNumber << " {\n"; - SW.indent(); - - ParseSubsection(Section.data() + Offset, SectionLength); - Offset = Offset + SectionLength; - - SW.unindent(); - SW.startLine() << "}\n"; - } -} -} - diff --git a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.h b/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.h deleted file mode 100644 index 6936b70..0000000 --- a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.h +++ /dev/null @@ -1,126 +0,0 @@ -//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMATTRIBUTEPARSER_H -#define LLVM_TOOLS_LLVM_READOBJ_ARMATTRIBUTEPARSER_H - -#include "llvm/Support/ARMBuildAttributes.h" -#include "llvm/Support/ScopedPrinter.h" - -namespace llvm { -class StringRef; - -class ARMAttributeParser { - ScopedPrinter &SW; - - struct DisplayHandler { - ARMBuildAttrs::AttrType Attribute; - void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType, - const uint8_t *, uint32_t &); - }; - static const DisplayHandler DisplayRoutines[]; - - uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset); - StringRef ParseString(const uint8_t *Data, uint32_t &Offset); - - void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - - void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc); - - void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag, - const uint8_t *Data, uint32_t &Offset); - void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void DSP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, - uint32_t &Offset); - - void ParseAttributeList(const uint8_t *Data, uint32_t &Offset, - uint32_t Length); - void ParseIndexList(const uint8_t *Data, uint32_t &Offset, - SmallVectorImpl<uint8_t> &IndexList); - void ParseSubsection(const uint8_t *Data, uint32_t Length); -public: - ARMAttributeParser(ScopedPrinter &SW) : SW(SW) {} - - void Parse(ArrayRef<uint8_t> Section); -}; - -} - -#endif - diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp index c83655f..74c4411 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "ARMWinEHPrinter.h" -#include "CodeView.h" #include "Error.h" #include "ObjDumper.h" #include "StackMapPrinter.h" @@ -22,8 +21,15 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" @@ -35,14 +41,16 @@ #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/CodeView/TypeTableCollection.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Support/COFF.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/Win64EH.h" @@ -55,17 +63,24 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::codeview; -using namespace llvm::msf; using namespace llvm::support; using namespace llvm::Win64EH; namespace { +struct LoadConfigTables { + uint64_t SEHTableVA = 0; + uint64_t SEHTableCount = 0; + uint32_t GuardFlags = 0; + uint64_t GuardFidTableVA = 0; + uint64_t GuardFidTableCount = 0; +}; + class COFFDumper : public ObjDumper { public: friend class COFFObjectDumpDelegate; COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer) - : ObjDumper(Writer), Obj(Obj), Writer(Writer) {} + : ObjDumper(Writer), Obj(Obj), Writer(Writer), Types(100) {} void printFileHeaders() override; void printSections() override; @@ -78,8 +93,11 @@ public: void printCOFFDirectives() override; void printCOFFBaseReloc() override; void printCOFFDebugDirectory() override; + void printCOFFResources() override; + void printCOFFLoadConfig() override; void printCodeViewDebugInfo() override; - void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) override; + void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, + llvm::codeview::TypeTableBuilder &CVTypes) override; void printStackMap() const override; private: void printSymbol(const SymbolRef &Sym); @@ -91,6 +109,11 @@ private: template <class PEHeader> void printPEHeader(const PEHeader *Hdr); void printBaseOfDataField(const pe32_header *Hdr); void printBaseOfDataField(const pe32plus_header *Hdr); + template <typename T> + void printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables); + typedef void (*PrintExtraCB)(raw_ostream &, const uint8_t *); + void printRVATable(uint64_t TableVA, uint64_t Count, uint64_t EntrySize, + PrintExtraCB PrintExtra = 0); void printCodeViewSymbolSection(StringRef SectionName, const SectionRef &Section); void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section); @@ -99,7 +122,7 @@ private: void printFileNameForOffset(StringRef Label, uint32_t FileOffset); void printTypeIndex(StringRef FieldName, TypeIndex TI) { // Forward to CVTypeDumper for simplicity. - CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB); + codeview::printTypeIndex(Writer, FieldName, TI, Types); } void printCodeViewSymbolsSubsection(StringRef Subsection, @@ -114,11 +137,19 @@ private: uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym = nullptr); + uint32_t countTotalTableEntries(ResourceSectionRef RSF, + const coff_resource_dir_table &Table, + StringRef Level); + + void printResourceDirectoryTable(ResourceSectionRef RSF, + const coff_resource_dir_table &Table, + StringRef Level); + void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec, StringRef SectionContents, StringRef Block); /// Given a .debug$S section, find the string table and file checksum table. - void initializeFileAndStringTables(StringRef Data); + void initializeFileAndStringTables(BinaryStreamReader &Reader); void cacheRelocations(); @@ -133,17 +164,23 @@ private: void printDelayImportedSymbols( const DelayImportDirectoryEntryRef &I, iterator_range<imported_symbol_iterator> Range); + ErrorOr<const coff_resource_dir_entry &> + getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, + uint32_t Index); typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; const llvm::object::COFFObjectFile *Obj; bool RelocCached = false; RelocMapTy RelocMap; - StringRef CVFileChecksumTable; - StringRef CVStringTable; + + DebugChecksumsSubsectionRef CVFileChecksumTable; + + DebugStringTableSubsectionRef CVStringTable; ScopedPrinter &Writer; - TypeDatabase TypeDB; + BinaryByteStream TypeContents; + LazyRandomTypeCollection Types; }; class COFFObjectDumpDelegate : public SymbolDumpDelegate { @@ -154,7 +191,7 @@ public: Sec = Obj->getCOFFSection(SR); } - uint32_t getRecordOffset(msf::StreamReader Reader) override { + uint32_t getRecordOffset(BinaryStreamReader Reader) override { ArrayRef<uint8_t> Data; if (auto EC = Reader.readLongestContiguousChunk(Data)) { llvm::consumeError(std::move(EC)); @@ -180,7 +217,9 @@ public: return CD.getFileNameForFileOffset(FileOffset); } - StringRef getStringTable() override { return CD.CVStringTable; } + DebugStringTableSubsectionRef getStringTable() override { + return CD.CVStringTable; + } private: COFFDumper &CD; @@ -296,6 +335,7 @@ static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = { LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ), LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ), LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64 ), LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ), LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ), LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ), @@ -495,19 +535,19 @@ WeakExternalCharacteristics[] = { }; static const EnumEntry<uint32_t> SubSectionTypes[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Lines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA), }; static const EnumEntry<uint32_t> FrameDataFlags[] = { @@ -523,6 +563,29 @@ static const EnumEntry<uint8_t> FileChecksumKindNames[] = { LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256), }; +static const EnumEntry<COFF::ResourceTypeID> ResourceTypeNames[]{ + {"kRT_CURSOR (ID 1)", COFF::RID_Cursor}, + {"kRT_BITMAP (ID 2)", COFF::RID_Bitmap}, + {"kRT_ICON (ID 3)", COFF::RID_Icon}, + {"kRT_MENU (ID 4)", COFF::RID_Menu}, + {"kRT_DIALOG (ID 5)", COFF::RID_Dialog}, + {"kRT_STRING (ID 6)", COFF::RID_String}, + {"kRT_FONTDIR (ID 7)", COFF::RID_FontDir}, + {"kRT_FONT (ID 8)", COFF::RID_Font}, + {"kRT_ACCELERATOR (ID 9)", COFF::RID_Accelerator}, + {"kRT_RCDATA (ID 10)", COFF::RID_RCData}, + {"kRT_MESSAGETABLE (ID 11)", COFF::RID_MessageTable}, + {"kRT_GROUP_CURSOR (ID 12)", COFF::RID_Group_Cursor}, + {"kRT_GROUP_ICON (ID 14)", COFF::RID_Group_Icon}, + {"kRT_VERSION (ID 16)", COFF::RID_Version}, + {"kRT_DLGINCLUDE (ID 17)", COFF::RID_DLGInclude}, + {"kRT_PLUGPLAY (ID 19)", COFF::RID_PlugPlay}, + {"kRT_VXD (ID 20)", COFF::RID_VXD}, + {"kRT_ANICURSOR (ID 21)", COFF::RID_AniCursor}, + {"kRT_ANIICON (ID 22)", COFF::RID_AniIcon}, + {"kRT_HTML (ID 23)", COFF::RID_HTML}, + {"kRT_MANIFEST (ID 24)", COFF::RID_Manifest}}; + template <typename T> static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, COFFSymbolRef Symbol, @@ -616,6 +679,7 @@ void COFFDumper::printDOSHeader(const dos_header *DH) { template <class PEHeader> void COFFDumper::printPEHeader(const PEHeader *Hdr) { DictScope D(W, "ImageOptionalHeader"); + W.printHex ("Magic", Hdr->Magic); W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion); W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion); W.printNumber("SizeOfCode", Hdr->SizeOfCode); @@ -697,6 +761,129 @@ void COFFDumper::printCOFFDebugDirectory() { } } +void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count, + uint64_t EntrySize, PrintExtraCB PrintExtra) { + uintptr_t TableStart, TableEnd; + error(Obj->getVaPtr(TableVA, TableStart)); + error(Obj->getVaPtr(TableVA + Count * EntrySize - 1, TableEnd)); + TableEnd++; + for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) { + uint32_t RVA = *reinterpret_cast<const ulittle32_t *>(I); + raw_ostream &OS = W.startLine(); + OS << "0x" << utohexstr(Obj->getImageBase() + RVA); + if (PrintExtra) + PrintExtra(OS, reinterpret_cast<const uint8_t *>(I)); + OS << '\n'; + } +} + +void COFFDumper::printCOFFLoadConfig() { + LoadConfigTables Tables; + if (Obj->is64()) + printCOFFLoadConfig(Obj->getLoadConfig64(), Tables); + else + printCOFFLoadConfig(Obj->getLoadConfig32(), Tables); + + if (Tables.SEHTableVA) { + ListScope LS(W, "SEHTable"); + printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4); + } + + if (Tables.GuardFidTableVA) { + ListScope LS(W, "GuardFidTable"); + if (Tables.GuardFlags & uint32_t(coff_guard_flags::FidTableHasFlags)) { + auto PrintGuardFlags = [](raw_ostream &OS, const uint8_t *Entry) { + uint8_t Flags = *reinterpret_cast<const uint8_t *>(Entry + 4); + if (Flags) + OS << " flags " << utohexstr(Flags); + }; + printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 5, + PrintGuardFlags); + } else { + printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4); + } + } +} + +template <typename T> +void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) { + if (!Conf) + return; + + ListScope LS(W, "LoadConfig"); + char FormattedTime[20] = {}; + time_t TDS = Conf->TimeDateStamp; + strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); + W.printHex("Size", Conf->Size); + + // Print everything before SecurityCookie. The vast majority of images today + // have all these fields. + if (Conf->Size < offsetof(T, SEHandlerTable)) + return; + W.printHex("TimeDateStamp", FormattedTime, TDS); + W.printHex("MajorVersion", Conf->MajorVersion); + W.printHex("MinorVersion", Conf->MinorVersion); + W.printHex("GlobalFlagsClear", Conf->GlobalFlagsClear); + W.printHex("GlobalFlagsSet", Conf->GlobalFlagsSet); + W.printHex("CriticalSectionDefaultTimeout", + Conf->CriticalSectionDefaultTimeout); + W.printHex("DeCommitFreeBlockThreshold", Conf->DeCommitFreeBlockThreshold); + W.printHex("DeCommitTotalFreeThreshold", Conf->DeCommitTotalFreeThreshold); + W.printHex("LockPrefixTable", Conf->LockPrefixTable); + W.printHex("MaximumAllocationSize", Conf->MaximumAllocationSize); + W.printHex("VirtualMemoryThreshold", Conf->VirtualMemoryThreshold); + W.printHex("ProcessHeapFlags", Conf->ProcessHeapFlags); + W.printHex("ProcessAffinityMask", Conf->ProcessAffinityMask); + W.printHex("CSDVersion", Conf->CSDVersion); + W.printHex("DependentLoadFlags", Conf->DependentLoadFlags); + W.printHex("EditList", Conf->EditList); + W.printHex("SecurityCookie", Conf->SecurityCookie); + + // Print the safe SEH table if present. + if (Conf->Size < offsetof(coff_load_configuration32, GuardCFCheckFunction)) + return; + W.printHex("SEHandlerTable", Conf->SEHandlerTable); + W.printNumber("SEHandlerCount", Conf->SEHandlerCount); + + Tables.SEHTableVA = Conf->SEHandlerTable; + Tables.SEHTableCount = Conf->SEHandlerCount; + + // Print everything before CodeIntegrity. (2015) + if (Conf->Size < offsetof(T, CodeIntegrity)) + return; + W.printHex("GuardCFCheckFunction", Conf->GuardCFCheckFunction); + W.printHex("GuardCFCheckDispatch", Conf->GuardCFCheckDispatch); + W.printHex("GuardCFFunctionTable", Conf->GuardCFFunctionTable); + W.printNumber("GuardCFFunctionCount", Conf->GuardCFFunctionCount); + W.printHex("GuardFlags", Conf->GuardFlags); + + Tables.GuardFidTableVA = Conf->GuardCFFunctionTable; + Tables.GuardFidTableCount = Conf->GuardCFFunctionCount; + Tables.GuardFlags = Conf->GuardFlags; + + // Print the rest. (2017) + if (Conf->Size < sizeof(T)) + return; + W.printHex("GuardAddressTakenIatEntryTable", + Conf->GuardAddressTakenIatEntryTable); + W.printNumber("GuardAddressTakenIatEntryCount", + Conf->GuardAddressTakenIatEntryCount); + W.printHex("GuardLongJumpTargetTable", Conf->GuardLongJumpTargetTable); + W.printNumber("GuardLongJumpTargetCount", Conf->GuardLongJumpTargetCount); + W.printHex("DynamicValueRelocTable", Conf->DynamicValueRelocTable); + W.printHex("CHPEMetadataPointer", Conf->CHPEMetadataPointer); + W.printHex("GuardRFFailureRoutine", Conf->GuardRFFailureRoutine); + W.printHex("GuardRFFailureRoutineFunctionPointer", + Conf->GuardRFFailureRoutineFunctionPointer); + W.printHex("DynamicValueRelocTableOffset", + Conf->DynamicValueRelocTableOffset); + W.printNumber("DynamicValueRelocTableSection", + Conf->DynamicValueRelocTableSection); + W.printHex("GuardRFVerifyStackPointerFunctionPointer", + Conf->GuardRFVerifyStackPointerFunctionPointer); + W.printHex("HotPatchTableOffset", Conf->HotPatchTableOffset); +} + void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) { W.printHex("BaseOfData", Hdr->BaseOfData); } @@ -719,30 +906,32 @@ void COFFDumper::printCodeViewDebugInfo() { } } -void COFFDumper::initializeFileAndStringTables(StringRef Data) { - while (!Data.empty() && (CVFileChecksumTable.data() == nullptr || - CVStringTable.data() == nullptr)) { +void COFFDumper::initializeFileAndStringTables(BinaryStreamReader &Reader) { + while (Reader.bytesRemaining() > 0 && + (!CVFileChecksumTable.valid() || !CVStringTable.valid())) { // The section consists of a number of subsection in the following format: // |SubSectionType|SubSectionSize|Contents...| uint32_t SubType, SubSectionSize; - error(consume(Data, SubType)); - error(consume(Data, SubSectionSize)); - if (SubSectionSize > Data.size()) - return error(object_error::parse_failed); - switch (ModuleSubstreamKind(SubType)) { - case ModuleSubstreamKind::FileChecksums: - CVFileChecksumTable = Data.substr(0, SubSectionSize); + error(Reader.readInteger(SubType)); + error(Reader.readInteger(SubSectionSize)); + + StringRef Contents; + error(Reader.readFixedString(Contents, SubSectionSize)); + + BinaryStreamRef ST(Contents, support::little); + switch (DebugSubsectionKind(SubType)) { + case DebugSubsectionKind::FileChecksums: + error(CVFileChecksumTable.initialize(ST)); break; - case ModuleSubstreamKind::StringTable: - CVStringTable = Data.substr(0, SubSectionSize); + case DebugSubsectionKind::StringTable: + error(CVStringTable.initialize(ST)); break; default: break; } + uint32_t PaddedSize = alignTo(SubSectionSize, 4); - if (PaddedSize > Data.size()) - error(object_error::parse_failed); - Data = Data.drop_front(PaddedSize); + error(Reader.skip(PaddedSize - SubSectionSize)); } } @@ -765,7 +954,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - initializeFileAndStringTables(Data); + BinaryStreamReader FSReader(Data, support::little); + initializeFileAndStringTables(FSReader); // TODO: Convert this over to using ModuleSubstreamVisitor. while (!Data.empty()) { @@ -799,20 +989,20 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, printBinaryBlockWithRelocs("SubSectionContents", Section, SectionContents, Contents); - switch (ModuleSubstreamKind(SubType)) { - case ModuleSubstreamKind::Symbols: + switch (DebugSubsectionKind(SubType)) { + case DebugSubsectionKind::Symbols: printCodeViewSymbolsSubsection(Contents, Section, SectionContents); break; - case ModuleSubstreamKind::InlineeLines: + case DebugSubsectionKind::InlineeLines: printCodeViewInlineeLines(Contents); break; - case ModuleSubstreamKind::FileChecksums: + case DebugSubsectionKind::FileChecksums: printCodeViewFileChecksums(Contents); break; - case ModuleSubstreamKind::Lines: { + case DebugSubsectionKind::Lines: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the // pointers for deferred processing. @@ -838,39 +1028,33 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, FunctionNames.push_back(LinkageName); break; } - case ModuleSubstreamKind::FrameData: { + case DebugSubsectionKind::FrameData: { // First four bytes is a relocation against the function. - msf::ByteStream S(Contents); - msf::StreamReader SR(S); - const uint32_t *CodePtr; - error(SR.readObject(CodePtr)); + BinaryStreamReader SR(Contents, llvm::support::little); + + DebugFrameDataSubsectionRef FrameData; + error(FrameData.initialize(SR)); + StringRef LinkageName; error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents, - CodePtr, LinkageName)); + FrameData.getRelocPtr(), LinkageName)); W.printString("LinkageName", LinkageName); // To find the active frame description, search this array for the // smallest PC range that includes the current PC. - while (!SR.empty()) { - const FrameData *FD; - error(SR.readObject(FD)); - - if (FD->FrameFunc >= CVStringTable.size()) - error(object_error::parse_failed); - - StringRef FrameFunc = - CVStringTable.drop_front(FD->FrameFunc).split('\0').first; + for (const auto &FD : FrameData) { + StringRef FrameFunc = error(CVStringTable.getString(FD.FrameFunc)); DictScope S(W, "FrameData"); - W.printHex("RvaStart", FD->RvaStart); - W.printHex("CodeSize", FD->CodeSize); - W.printHex("LocalSize", FD->LocalSize); - W.printHex("ParamsSize", FD->ParamsSize); - W.printHex("MaxStackSize", FD->MaxStackSize); + W.printHex("RvaStart", FD.RvaStart); + W.printHex("CodeSize", FD.CodeSize); + W.printHex("LocalSize", FD.LocalSize); + W.printHex("ParamsSize", FD.ParamsSize); + W.printHex("MaxStackSize", FD.MaxStackSize); W.printString("FrameFunc", FrameFunc); - W.printHex("PrologSize", FD->PrologSize); - W.printHex("SavedRegsSize", FD->SavedRegsSize); - W.printFlags("Flags", FD->Flags, makeArrayRef(FrameDataFlags)); + W.printHex("PrologSize", FD.PrologSize); + W.printHex("SavedRegsSize", FD.SavedRegsSize); + W.printFlags("Flags", FD.Flags, makeArrayRef(FrameDataFlags)); } break; } @@ -889,45 +1073,28 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, ListScope S(W, "FunctionLineTable"); W.printString("LinkageName", Name); - DataExtractor DE(FunctionLineTables[Name], true, 4); - uint32_t Offset = 6; // Skip relocations. - uint16_t Flags = DE.getU16(&Offset); - W.printHex("Flags", Flags); - bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns; - uint32_t FunctionSize = DE.getU32(&Offset); - W.printHex("CodeSize", FunctionSize); - while (DE.isValidOffset(Offset)) { - // For each range of lines with the same filename, we have a segment - // in the line table. The filename string is accessed using double - // indirection to the string table subsection using the index subsection. - uint32_t OffsetInIndex = DE.getU32(&Offset), - NumLines = DE.getU32(&Offset), - FullSegmentSize = DE.getU32(&Offset); - - uint32_t ColumnOffset = Offset + 8 * NumLines; - DataExtractor ColumnDE(DE.getData(), true, 4); - - if (FullSegmentSize != - 12 + 8 * NumLines + (HasColumnInformation ? 4 * NumLines : 0)) { - error(object_error::parse_failed); - return; - } + BinaryStreamReader Reader(FunctionLineTables[Name], support::little); + + DebugLinesSubsectionRef LineInfo; + error(LineInfo.initialize(Reader)); + + W.printHex("Flags", LineInfo.header()->Flags); + W.printHex("CodeSize", LineInfo.header()->CodeSize); + for (const auto &Entry : LineInfo) { ListScope S(W, "FilenameSegment"); - printFileNameForOffset("Filename", OffsetInIndex); - for (unsigned LineIdx = 0; - LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) { - // Then go the (PC, LineNumber) pairs. The line number is stored in the - // least significant 31 bits of the respective word in the table. - uint32_t PC = DE.getU32(&Offset), LineData = DE.getU32(&Offset); - if (PC >= FunctionSize) { + printFileNameForOffset("Filename", Entry.NameIndex); + uint32_t ColumnIndex = 0; + for (const auto &Line : Entry.LineNumbers) { + if (Line.Offset >= LineInfo.header()->CodeSize) { error(object_error::parse_failed); return; } - char Buffer[32]; - format("+0x%X", PC).snprint(Buffer, 32); - ListScope PCScope(W, Buffer); - LineInfo LI(LineData); + + std::string PC = formatv("+{0:X}", uint32_t(Line.Offset)); + ListScope PCScope(W, PC); + codeview::LineInfo LI(Line.Flags); + if (LI.isAlwaysStepInto()) W.printString("StepInto", StringRef("Always")); else if (LI.isNeverStepInto()) @@ -936,19 +1103,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, W.printNumber("LineNumberStart", LI.getStartLine()); W.printNumber("LineNumberEndDelta", LI.getLineDelta()); W.printBoolean("IsStatement", LI.isStatement()); - if (HasColumnInformation && - ColumnDE.isValidOffsetForDataOfSize(ColumnOffset, 4)) { - uint16_t ColStart = ColumnDE.getU16(&ColumnOffset); - W.printNumber("ColStart", ColStart); - uint16_t ColEnd = ColumnDE.getU16(&ColumnOffset); - W.printNumber("ColEnd", ColEnd); - } - } - // Skip over the column data. - if (HasColumnInformation) { - for (unsigned LineIdx = 0; - LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) { - DE.getU32(&Offset); + if (LineInfo.hasColumnInfo()) { + W.printNumber("ColStart", Entry.Columns[ColumnIndex].StartColumn); + W.printNumber("ColEnd", Entry.Columns[ColumnIndex].EndColumn); + ++ColumnIndex; } } } @@ -962,12 +1120,10 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, Subsection.bytes_end()); auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj, SectionContents); - - CVSymbolDumper CVSD(W, TypeDB, std::move(CODD), + CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD), opts::CodeViewSubsectionBytes); - ByteStream Stream(BinaryData); CVSymbolArray Symbols; - StreamReader Reader(Stream); + BinaryStreamReader Reader(BinaryData, llvm::support::little); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) { consumeError(std::move(EC)); W.flush(); @@ -982,58 +1138,39 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, } void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { - msf::ByteStream S(Subsection); - msf::StreamReader SR(S); - while (!SR.empty()) { + BinaryStreamRef Stream(Subsection, llvm::support::little); + DebugChecksumsSubsectionRef Checksums; + error(Checksums.initialize(Stream)); + + for (auto &FC : Checksums) { DictScope S(W, "FileChecksum"); - const FileChecksum *FC; - error(SR.readObject(FC)); - if (FC->FileNameOffset >= CVStringTable.size()) - error(object_error::parse_failed); - StringRef Filename = - CVStringTable.drop_front(FC->FileNameOffset).split('\0').first; - W.printHex("Filename", Filename, FC->FileNameOffset); - W.printHex("ChecksumSize", FC->ChecksumSize); - W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind), + + StringRef Filename = error(CVStringTable.getString(FC.FileNameOffset)); + W.printHex("Filename", Filename, FC.FileNameOffset); + W.printHex("ChecksumSize", FC.Checksum.size()); + W.printEnum("ChecksumKind", uint8_t(FC.Kind), makeArrayRef(FileChecksumKindNames)); - if (FC->ChecksumSize >= SR.bytesRemaining()) - error(object_error::parse_failed); - ArrayRef<uint8_t> ChecksumBytes; - error(SR.readBytes(ChecksumBytes, FC->ChecksumSize)); - W.printBinary("ChecksumBytes", ChecksumBytes); - unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) - - sizeof(FileChecksum); - PaddedSize -= ChecksumBytes.size(); - if (PaddedSize > SR.bytesRemaining()) - error(object_error::parse_failed); - error(SR.skip(PaddedSize)); + + W.printBinary("ChecksumBytes", FC.Checksum); } } void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { - msf::ByteStream S(Subsection); - msf::StreamReader SR(S); - uint32_t Signature; - error(SR.readInteger(Signature)); - bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles); - - while (!SR.empty()) { - const InlineeSourceLine *ISL; - error(SR.readObject(ISL)); + BinaryStreamReader SR(Subsection, llvm::support::little); + DebugInlineeLinesSubsectionRef Lines; + error(Lines.initialize(SR)); + + for (auto &Line : Lines) { DictScope S(W, "InlineeSourceLine"); - printTypeIndex("Inlinee", ISL->Inlinee); - printFileNameForOffset("FileID", ISL->FileID); - W.printNumber("SourceLineNum", ISL->SourceLineNum); - - if (HasExtraFiles) { - uint32_t ExtraFileCount; - error(SR.readInteger(ExtraFileCount)); - W.printNumber("ExtraFileCount", ExtraFileCount); + printTypeIndex("Inlinee", Line.Header->Inlinee); + printFileNameForOffset("FileID", Line.Header->FileID); + W.printNumber("SourceLineNum", Line.Header->SourceLineNum); + + if (Lines.hasExtraFiles()) { + W.printNumber("ExtraFileCount", Line.ExtraFiles.size()); ListScope ExtraFiles(W, "ExtraFiles"); - for (unsigned I = 0; I < ExtraFileCount; ++I) { - uint32_t FileID; - error(SR.readInteger(FileID)); - printFileNameForOffset("FileID", FileID); + for (const auto &FID : Line.ExtraFiles) { + printFileNameForOffset("FileID", FID); } } } @@ -1041,30 +1178,24 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) { // The file checksum subsection should precede all references to it. - if (!CVFileChecksumTable.data() || !CVStringTable.data()) - error(object_error::parse_failed); - // Check if the file checksum table offset is valid. - if (FileOffset >= CVFileChecksumTable.size()) + if (!CVFileChecksumTable.valid() || !CVStringTable.valid()) error(object_error::parse_failed); - // The string table offset comes first before the file checksum. - StringRef Data = CVFileChecksumTable.drop_front(FileOffset); - uint32_t StringOffset; - error(consume(Data, StringOffset)); + auto Iter = CVFileChecksumTable.getArray().at(FileOffset); - // Check if the string table offset is valid. - if (StringOffset >= CVStringTable.size()) + // Check if the file checksum table offset is valid. + if (Iter == CVFileChecksumTable.end()) error(object_error::parse_failed); - // Return the null-terminated string. - return CVStringTable.drop_front(StringOffset).split('\0').first; + return error(CVStringTable.getString(Iter->FileNameOffset)); } void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) { W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset); } -void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVTypes) { +void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVIDs, + TypeTableBuilder &CVTypes) { for (const SectionRef &S : Obj->sections()) { StringRef SectionName; error(S.getName(SectionName)); @@ -1075,19 +1206,17 @@ void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVTypes) { error(consume(Data, Magic)); if (Magic != 4) error(object_error::parse_failed); - ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()), - Data.size()); - ByteStream Stream(Bytes); + CVTypeArray Types; - StreamReader Reader(Stream); + BinaryStreamReader Reader(Data, llvm::support::little); if (auto EC = Reader.readArray(Types, Reader.getLength())) { consumeError(std::move(EC)); W.flush(); error(object_error::parse_failed); } - - if (!mergeTypeStreams(CVTypes, Types)) - return error(object_error::parse_failed); + SmallVector<TypeIndex, 128> SourceToDest; + if (auto EC = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types)) + return error(std::move(EC)); } } } @@ -1108,12 +1237,11 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - CVTypeDumper CVTD(TypeDB); - TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes); - if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) { - W.flush(); - error(llvm::errorToErrorCode(std::move(EC))); - } + Types.reset(Data, 100); + + TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes); + error(codeview::visitTypeStream(Types, TDV)); + W.flush(); } void COFFDumper::printSections() { @@ -1435,12 +1563,18 @@ void COFFDumper::printCOFFImports() { StringRef Name; error(I.getName(Name)); W.printString("Name", Name); - uint32_t Addr; - error(I.getImportLookupTableRVA(Addr)); - W.printHex("ImportLookupTableRVA", Addr); - error(I.getImportAddressTableRVA(Addr)); - W.printHex("ImportAddressTableRVA", Addr); - printImportedSymbols(I.imported_symbols()); + uint32_t ILTAddr; + error(I.getImportLookupTableRVA(ILTAddr)); + W.printHex("ImportLookupTableRVA", ILTAddr); + uint32_t IATAddr; + error(I.getImportAddressTableRVA(IATAddr)); + W.printHex("ImportAddressTableRVA", IATAddr); + // The import lookup table can be missing with certain older linkers, so + // fall back to the import address table in that case. + if (ILTAddr) + printImportedSymbols(I.lookup_table_symbols()); + else + printImportedSymbols(I.imported_symbols()); } // Delay imports @@ -1502,7 +1636,11 @@ static StringRef getBaseRelocTypeName(uint8_t Type) { case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ"; case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)"; case COFF::IMAGE_REL_BASED_DIR64: return "DIR64"; - default: return "unknown (" + llvm::utostr(Type) + ")"; + default: { + static std::string Result; + Result = "unknown (" + llvm::utostr(Type) + ")"; + return Result; + } } } @@ -1519,6 +1657,127 @@ void COFFDumper::printCOFFBaseReloc() { } } +void COFFDumper::printCOFFResources() { + ListScope ResourcesD(W, "Resources"); + for (const SectionRef &S : Obj->sections()) { + StringRef Name; + error(S.getName(Name)); + if (!Name.startswith(".rsrc")) + continue; + + StringRef Ref; + error(S.getContents(Ref)); + + if ((Name == ".rsrc") || (Name == ".rsrc$01")) { + ResourceSectionRef RSF(Ref); + auto &BaseTable = unwrapOrError(RSF.getBaseTable()); + W.printNumber("Total Number of Resources", + countTotalTableEntries(RSF, BaseTable, "Type")); + W.printHex("Base Table Address", + Obj->getCOFFSection(S)->PointerToRawData); + W.startLine() << "\n"; + printResourceDirectoryTable(RSF, BaseTable, "Type"); + } + if (opts::SectionData) + W.printBinaryBlock(Name.str() + " Data", Ref); + } +} + +uint32_t +COFFDumper::countTotalTableEntries(ResourceSectionRef RSF, + const coff_resource_dir_table &Table, + StringRef Level) { + uint32_t TotalEntries = 0; + for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries; + i++) { + auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i)); + if (Entry.Offset.isSubDir()) { + StringRef NextLevel; + if (Level == "Name") + NextLevel = "Language"; + else + NextLevel = "Name"; + auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry)); + TotalEntries += countTotalTableEntries(RSF, NextTable, NextLevel); + } else { + TotalEntries += 1; + } + } + return TotalEntries; +} + +void COFFDumper::printResourceDirectoryTable( + ResourceSectionRef RSF, const coff_resource_dir_table &Table, + StringRef Level) { + + W.printNumber("Number of String Entries", Table.NumberOfNameEntries); + W.printNumber("Number of ID Entries", Table.NumberOfIDEntries); + + // Iterate through level in resource directory tree. + for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries; + i++) { + auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i)); + StringRef Name; + SmallString<20> IDStr; + raw_svector_ostream OS(IDStr); + if (i < Table.NumberOfNameEntries) { + ArrayRef<UTF16> RawEntryNameString = unwrapOrError(RSF.getEntryNameString(Entry)); + std::vector<UTF16> EndianCorrectedNameString; + if (llvm::sys::IsBigEndianHost) { + EndianCorrectedNameString.resize(RawEntryNameString.size() + 1); + std::copy(RawEntryNameString.begin(), RawEntryNameString.end(), + EndianCorrectedNameString.begin() + 1); + EndianCorrectedNameString[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED; + RawEntryNameString = makeArrayRef(EndianCorrectedNameString); + } + std::string EntryNameString; + if (!llvm::convertUTF16ToUTF8String(RawEntryNameString, EntryNameString)) + error(object_error::parse_failed); + OS << ": "; + OS << EntryNameString; + } else { + if (Level == "Type") { + ScopedPrinter Printer(OS); + Printer.printEnum("", Entry.Identifier.ID, + makeArrayRef(ResourceTypeNames)); + IDStr = IDStr.slice(0, IDStr.find_first_of(")", 0) + 1); + } else { + OS << ": (ID " << Entry.Identifier.ID << ")"; + } + } + Name = StringRef(IDStr); + ListScope ResourceType(W, Level.str() + Name.str()); + if (Entry.Offset.isSubDir()) { + W.printHex("Table Offset", Entry.Offset.value()); + StringRef NextLevel; + if (Level == "Name") + NextLevel = "Language"; + else + NextLevel = "Name"; + auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry)); + printResourceDirectoryTable(RSF, NextTable, NextLevel); + } else { + W.printHex("Entry Offset", Entry.Offset.value()); + char FormattedTime[20] = {}; + time_t TDS = time_t(Table.TimeDateStamp); + strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); + W.printHex("Time/Date Stamp", FormattedTime, Table.TimeDateStamp); + W.printNumber("Major Version", Table.MajorVersion); + W.printNumber("Minor Version", Table.MinorVersion); + W.printNumber("Characteristics", Table.Characteristics); + } + } +} + +ErrorOr<const coff_resource_dir_entry &> +COFFDumper::getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, + uint32_t Index) { + if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) + return object_error::parse_failed; + auto TablePtr = reinterpret_cast<const coff_resource_dir_entry *>(&Table + 1); + return TablePtr[Index]; +} + void COFFDumper::printStackMap() const { object::SectionRef StackMapSection; for (auto Sec : Obj->sections()) { @@ -1549,20 +1808,30 @@ void COFFDumper::printStackMap() const { } void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer, + llvm::codeview::TypeTableBuilder &IDTable, llvm::codeview::TypeTableBuilder &CVTypes) { // Flatten it first, then run our dumper on it. - ListScope S(Writer, "MergedTypeStream"); - SmallString<0> Buf; + SmallString<0> TypeBuf; CVTypes.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) { - Buf.append(Record.begin(), Record.end()); + TypeBuf.append(Record.begin(), Record.end()); }); - TypeDatabase TypeDB; - CVTypeDumper CVTD(TypeDB); - TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes); - if (auto EC = - CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()}, TDV)) { + TypeTableCollection TpiTypes(CVTypes.records()); + { + ListScope S(Writer, "MergedTypeStream"); + TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes); + error(codeview::visitTypeStream(TpiTypes, TDV)); + Writer.flush(); + } + + // Flatten the id stream and print it next. The ID stream refers to names from + // the type stream. + TypeTableCollection IpiTypes(IDTable.records()); + { + ListScope S(Writer, "MergedIDStream"); + TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes); + TDV.setIpiTypes(IpiTypes); + error(codeview::visitTypeStream(IpiTypes, TDV)); Writer.flush(); - error(llvm::errorToErrorCode(std::move(EC))); } } diff --git a/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp index 83715e6..c5b8bf7 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp @@ -15,9 +15,9 @@ #include "Error.h" #include "ObjDumper.h" #include "llvm-readobj.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" -#include "llvm/Support/COFF.h" using namespace llvm::object; diff --git a/contrib/llvm/tools/llvm-readobj/CodeView.h b/contrib/llvm/tools/llvm-readobj/CodeView.h deleted file mode 100644 index cf71396..0000000 --- a/contrib/llvm/tools/llvm-readobj/CodeView.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- CodeView.h - On-disk record types for CodeView ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file provides data structures useful for consuming on-disk -/// CodeView. It is based on information published by Microsoft at -/// https://github.com/Microsoft/microsoft-pdb/. -/// -//===----------------------------------------------------------------------===// - -// FIXME: Find a home for this in include/llvm/DebugInfo/CodeView/. - -#ifndef LLVM_READOBJ_CODEVIEW_H -#define LLVM_READOBJ_CODEVIEW_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/Support/Endian.h" - -namespace llvm { -namespace codeview { - -using llvm::support::ulittle16_t; -using llvm::support::ulittle32_t; - -/// Data in the the SUBSEC_FRAMEDATA subection. -struct FrameData { - ulittle32_t RvaStart; - ulittle32_t CodeSize; - ulittle32_t LocalSize; - ulittle32_t ParamsSize; - ulittle32_t MaxStackSize; - ulittle32_t FrameFunc; - ulittle16_t PrologSize; - ulittle16_t SavedRegsSize; - ulittle32_t Flags; - enum : uint32_t { - HasSEH = 1 << 0, - HasEH = 1 << 1, - IsFunctionStart = 1 << 2, - }; -}; - - -} // namespace codeview -} // namespace llvm - -#endif // LLVM_READOBJ_CODEVIEW_H diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp index 997af56..5698420 100644 --- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1,4 +1,4 @@ -//===-- ELFDumper.cpp - ELF-specific dumper ---------------------*- C++ -*-===// +//===- ELFDumper.cpp - ELF-specific dumper --------------------------------===// // // The LLVM Compiler Infrastructure // @@ -12,24 +12,49 @@ /// //===----------------------------------------------------------------------===// -#include "ARMAttributeParser.h" #include "ARMEHABIPrinter.h" #include "Error.h" #include "ObjDumper.h" #include "StackMapPrinter.h" #include "llvm-readobj.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/StackMapParser.h" +#include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cinttypes> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iterator> +#include <memory> +#include <string> +#include <system_error> +#include <vector> using namespace llvm; using namespace llvm::object; @@ -49,28 +74,28 @@ using namespace ELF; return std::string(#enum).substr(3); #define TYPEDEF_ELF_TYPES(ELFT) \ - typedef ELFFile<ELFT> ELFO; \ - typedef typename ELFO::Elf_Shdr Elf_Shdr; \ - typedef typename ELFO::Elf_Sym Elf_Sym; \ - typedef typename ELFO::Elf_Dyn Elf_Dyn; \ - typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; \ - typedef typename ELFO::Elf_Rel Elf_Rel; \ - typedef typename ELFO::Elf_Rela Elf_Rela; \ - typedef typename ELFO::Elf_Rel_Range Elf_Rel_Range; \ - typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; \ - typedef typename ELFO::Elf_Phdr Elf_Phdr; \ - typedef typename ELFO::Elf_Half Elf_Half; \ - typedef typename ELFO::Elf_Ehdr Elf_Ehdr; \ - typedef typename ELFO::Elf_Word Elf_Word; \ - typedef typename ELFO::Elf_Hash Elf_Hash; \ - typedef typename ELFO::Elf_GnuHash Elf_GnuHash; \ - typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range; \ - typedef typename ELFO::Elf_Versym Elf_Versym; \ - typedef typename ELFO::Elf_Verneed Elf_Verneed; \ - typedef typename ELFO::Elf_Vernaux Elf_Vernaux; \ - typedef typename ELFO::Elf_Verdef Elf_Verdef; \ - typedef typename ELFO::Elf_Verdaux Elf_Verdaux; \ - typedef typename ELFO::uintX_t uintX_t; + using ELFO = ELFFile<ELFT>; \ + using Elf_Shdr = typename ELFO::Elf_Shdr; \ + using Elf_Sym = typename ELFO::Elf_Sym; \ + using Elf_Dyn = typename ELFO::Elf_Dyn; \ + using Elf_Dyn_Range = typename ELFO::Elf_Dyn_Range; \ + using Elf_Rel = typename ELFO::Elf_Rel; \ + using Elf_Rela = typename ELFO::Elf_Rela; \ + using Elf_Rel_Range = typename ELFO::Elf_Rel_Range; \ + using Elf_Rela_Range = typename ELFO::Elf_Rela_Range; \ + using Elf_Phdr = typename ELFO::Elf_Phdr; \ + using Elf_Half = typename ELFO::Elf_Half; \ + using Elf_Ehdr = typename ELFO::Elf_Ehdr; \ + using Elf_Word = typename ELFO::Elf_Word; \ + using Elf_Hash = typename ELFO::Elf_Hash; \ + using Elf_GnuHash = typename ELFO::Elf_GnuHash; \ + using Elf_Sym_Range = typename ELFO::Elf_Sym_Range; \ + using Elf_Versym = typename ELFO::Elf_Versym; \ + using Elf_Verneed = typename ELFO::Elf_Verneed; \ + using Elf_Vernaux = typename ELFO::Elf_Vernaux; \ + using Elf_Verdef = typename ELFO::Elf_Verdef; \ + using Elf_Verdaux = typename ELFO::Elf_Verdaux; \ + using uintX_t = typename ELFO::uintX_t; namespace { @@ -81,15 +106,16 @@ template <class ELFT> class DumpStyle; /// the size, entity size and virtual address are different entries in arbitrary /// order (DT_REL, DT_RELSZ, DT_RELENT for example). struct DynRegionInfo { - DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} + DynRegionInfo() = default; DynRegionInfo(const void *A, uint64_t S, uint64_t ES) : Addr(A), Size(S), EntSize(ES) {} + /// \brief Address in current address space. - const void *Addr; + const void *Addr = nullptr; /// \brief Size in bytes of the region. - uint64_t Size; + uint64_t Size = 0; /// \brief Size of each entity in the region. - uint64_t EntSize; + uint64_t EntSize = 0; template <typename Type> ArrayRef<Type> getAsArrayRef() const { const Type *Start = reinterpret_cast<const Type *>(Addr); @@ -129,7 +155,7 @@ public: void printMipsReginfo() override; void printMipsOptions() override; - void printAMDGPURuntimeMD() override; + void printAMDGPUCodeObjectMetadata() override; void printStackMap() const override; @@ -139,6 +165,7 @@ public: private: std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; + TYPEDEF_ELF_TYPES(ELFT) DynRegionInfo checkDRI(DynRegionInfo DRI) { @@ -196,6 +223,7 @@ private: : PointerIntPair<const void *, 1>(verdef, 0) {} VersionMapEntry(const Elf_Vernaux *vernaux) : PointerIntPair<const void *, 1>(vernaux, 1) {} + bool isNull() const { return getPointer() == nullptr; } bool isVerdef() const { return !isNull() && getInt() == 0; } bool isVernaux() const { return !isNull() && getInt() == 1; } @@ -262,10 +290,11 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { template <typename ELFT> class DumpStyle { public: using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr; - using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym; + using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym; DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {} - virtual ~DumpStyle() {} + virtual ~DumpStyle() = default; + virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0; virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0; virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0; @@ -274,9 +303,7 @@ public: virtual void printDynamicSymbols(const ELFFile<ELFT> *Obj) = 0; virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0; virtual void printSymtabMessage(const ELFFile<ELFT> *obj, StringRef Name, - size_t Offset) { - return; - } + size_t Offset) {} virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol, const Elf_Sym *FirstSym, StringRef StrTable, bool IsDynamic) = 0; @@ -284,16 +311,20 @@ public: virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; const ELFDumper<ELFT> *dumper() const { return Dumper; } + private: const ELFDumper<ELFT> *Dumper; }; template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> { formatted_raw_ostream OS; + public: TYPEDEF_ELF_TYPES(ELFT) + GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) : DumpStyle<ELFT>(Dumper), OS(W.getOStream()) {} + void printFileHeaders(const ELFO *Obj) override; void printGroupSections(const ELFFile<ELFT> *Obj) override; void printRelocations(const ELFO *Obj) override; @@ -301,8 +332,8 @@ public: void printSymbols(const ELFO *Obj) override; void printDynamicSymbols(const ELFO *Obj) override; void printDynamicRelocations(const ELFO *Obj) override; - virtual void printSymtabMessage(const ELFO *Obj, StringRef Name, - size_t Offset) override; + void printSymtabMessage(const ELFO *Obj, StringRef Name, + size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile<ELFT> *Obj) override; void printNotes(const ELFFile<ELFT> *Obj) override; @@ -311,6 +342,7 @@ private: struct Field { StringRef Str; unsigned Column; + Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} Field(unsigned Col) : Str(""), Column(Col) {} }; @@ -348,6 +380,7 @@ private: template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> { public: TYPEDEF_ELF_TYPES(ELFT) + LLVMStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) : DumpStyle<ELFT>(Dumper), W(W) {} @@ -368,10 +401,11 @@ private: void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, StringRef StrTable, bool IsDynamic) override; + ScopedPrinter &W; }; -} // namespace +} // end anonymous namespace namespace llvm { @@ -405,7 +439,7 @@ std::error_code createELFDumper(const object::ObjectFile *Obj, return readobj_error::unsupported_obj_file_format; } -} // namespace llvm +} // end namespace llvm // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. @@ -525,8 +559,8 @@ static void printVersionDefinitionSection(ELFDumper<ELFT> *Dumper, const ELFO *Obj, const typename ELFO::Elf_Shdr *Sec, ScopedPrinter &W) { - typedef typename ELFO::Elf_Verdef VerDef; - typedef typename ELFO::Elf_Verdaux VerdAux; + using VerDef = typename ELFO::Elf_Verdef; + using VerdAux = typename ELFO::Elf_Verdaux; DictScope SD(W, "SHT_GNU_verdef"); if (!Sec) @@ -581,8 +615,8 @@ static void printVersionDependencySection(ELFDumper<ELFT> *Dumper, const ELFO *Obj, const typename ELFO::Elf_Shdr *Sec, ScopedPrinter &W) { - typedef typename ELFO::Elf_Verneed VerNeed; - typedef typename ELFO::Elf_Vernaux VernAux; + using VerNeed = typename ELFO::Elf_Verneed; + using VernAux = typename ELFO::Elf_Vernaux; DictScope SD(W, "SHT_GNU_verneed"); if (!Sec) @@ -978,61 +1012,9 @@ static const EnumEntry<unsigned> ElfSymbolTypes[] = { {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}}; static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { - { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }, - { "AMDGPU_HSA_INDIRECT_FUNCTION", ELF::STT_AMDGPU_HSA_INDIRECT_FUNCTION }, - { "AMDGPU_HSA_METADATA", ELF::STT_AMDGPU_HSA_METADATA } + { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } }; -static const char *getElfSectionType(unsigned Arch, unsigned Type) { - switch (Arch) { - case ELF::EM_ARM: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_EXIDX); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION); - } - case ELF::EM_HEXAGON: - switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); } - case ELF::EM_X86_64: - switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); } - case ELF::EM_MIPS: - case ELF::EM_MIPS_RS3_LE: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_REGINFO); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_OPTIONS); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS); - } - } - - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_NULL ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_PROGBITS ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_STRTAB ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_RELA ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_HASH ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNAMIC ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOTE ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOBITS ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_REL ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_SHLIB ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNSYM ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_INIT_ARRAY ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_FINI_ARRAY ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_PREINIT_ARRAY ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GROUP ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_HASH ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verdef ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verneed ); - LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_versym ); - default: return ""; - } -} - static const char *getGroupType(uint32_t Flag) { if (Flag & ELF::GRP_COMDAT) return "COMDAT"; @@ -1062,13 +1044,6 @@ static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION) }; -static const EnumEntry<unsigned> ElfAMDGPUSectionFlags[] = { - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_GLOBAL), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_READONLY), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_CODE), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT) -}; - static const EnumEntry<unsigned> ElfARMSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) }; @@ -1127,13 +1102,6 @@ static const char *getElfSegmentType(unsigned Arch, unsigned Type) { // Check potentially overlapped processor-specific // program header type. switch (Arch) { - case ELF::EM_AMDGPU: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT); - } case ELF::EM_ARM: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); @@ -1189,14 +1157,6 @@ static std::string getElfPtType(unsigned Arch, unsigned Type) { default: // All machine specific PT_* types switch (Arch) { - case ELF::EM_AMDGPU: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT); - } - return ""; case ELF::EM_ARM: if (Type == ELF::PT_ARM_EXIDX) return "EXIDX"; @@ -1312,7 +1272,6 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { template <typename ELFT> ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) : ObjDumper(Writer), Obj(Obj) { - SmallVector<const Elf_Phdr *, 4> LoadSegments; for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type == ELF::PT_DYNAMIC) { @@ -1573,6 +1532,7 @@ static const char *getTypeString(unsigned Arch, uint64_t Type) { LLVM_READOBJ_TYPE_CASE(TLSDESC_PLT); LLVM_READOBJ_TYPE_CASE(TLSDESC_GOT); LLVM_READOBJ_TYPE_CASE(AUXILIARY); + LLVM_READOBJ_TYPE_CASE(FILTER); default: return "unknown"; } } @@ -1641,8 +1601,8 @@ static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { template <typename T, typename TFlag> void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { - typedef EnumEntry<TFlag> FlagEntry; - typedef SmallVector<FlagEntry, 10> FlagVector; + using FlagEntry = EnumEntry<TFlag>; + using FlagVector = SmallVector<FlagEntry, 10>; FlagVector SetFlags; for (const auto &Flag : Flags) { @@ -1665,6 +1625,10 @@ StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { return StringRef(DynamicStringTable.data() + Value); } +static void printLibrary(raw_ostream &OS, const Twine &Tag, const Twine &Name) { + OS << Tag << ": [" << Name << "]"; +} + template <class ELFT> void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { raw_ostream &OS = W.getOStream(); @@ -1728,13 +1692,16 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { OS << Value << " (bytes)"; break; case DT_NEEDED: - OS << "SharedLibrary (" << getDynamicString(Value) << ")"; + printLibrary(OS, "Shared library", getDynamicString(Value)); break; case DT_SONAME: - OS << "LibrarySoname (" << getDynamicString(Value) << ")"; + printLibrary(OS, "Library soname", getDynamicString(Value)); break; case DT_AUXILIARY: - OS << "Auxiliary library: [" << getDynamicString(Value) << "]"; + printLibrary(OS, "Auxiliary library", getDynamicString(Value)); + break; + case DT_FILTER: + printLibrary(OS, "Filter library", getDynamicString(Value)); break; case DT_RPATH: case DT_RUNPATH: @@ -1761,6 +1728,7 @@ void ELFDumper<ELFT>::printUnwindInfo() { } namespace { + template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { @@ -1770,7 +1738,8 @@ template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { } W.startLine() << "UnwindInfo not implemented.\n"; } -} + +} // end anonymous namespace template<class ELFT> void ELFDumper<ELFT>::printDynamicTable() { @@ -1816,7 +1785,7 @@ template<class ELFT> void ELFDumper<ELFT>::printNeededLibraries() { ListScope D(W, "NeededLibraries"); - typedef std::vector<StringRef> LibsTy; + using LibsTy = std::vector<StringRef>; LibsTy Libs; for (const auto &Entry : dynamic_table()) @@ -1870,6 +1839,7 @@ void ELFDumper<ELFT>::printAttributes() { } namespace { + template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; @@ -1892,16 +1862,15 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { if (Contents.size() == 1) continue; - ARMAttributeParser(W).Parse(Contents); + ARMAttributeParser(&W).Parse(Contents, true); } } -} -namespace { template <class ELFT> class MipsGOTParser { public: TYPEDEF_ELF_TYPES(ELFT) - typedef typename ELFO::Elf_Addr GOTEntry; + using GOTEntry = typename ELFO::Elf_Addr; + MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, Elf_Dyn_Range DynTable, ScopedPrinter &W); @@ -1912,11 +1881,11 @@ private: ELFDumper<ELFT> *Dumper; const ELFO *Obj; ScopedPrinter &W; - llvm::Optional<uint64_t> DtPltGot; - llvm::Optional<uint64_t> DtLocalGotNum; - llvm::Optional<uint64_t> DtGotSym; - llvm::Optional<uint64_t> DtMipsPltGot; - llvm::Optional<uint64_t> DtJmpRel; + Optional<uint64_t> DtPltGot; + Optional<uint64_t> DtLocalGotNum; + Optional<uint64_t> DtGotSym; + Optional<uint64_t> DtMipsPltGot; + Optional<uint64_t> DtJmpRel; std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const; const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum); @@ -1932,7 +1901,8 @@ private: const GOTEntry *It, StringRef StrTable, const Elf_Sym *Sym); }; -} + +} // end anonymous namespace template <class ELFT> MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, @@ -2356,7 +2326,7 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { } } -template <class ELFT> void ELFDumper<ELFT>::printAMDGPURuntimeMD() { +template <class ELFT> void ELFDumper<ELFT>::printAMDGPUCodeObjectMetadata() { const Elf_Shdr *Shdr = findSectionByName(*Obj, ".note"); if (!Shdr) { W.startLine() << "There is no .note section in the file.\n"; @@ -2364,7 +2334,7 @@ template <class ELFT> void ELFDumper<ELFT>::printAMDGPURuntimeMD() { } ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); - const uint32_t RuntimeMDNoteType = 7; + const uint32_t CodeObjectMetadataNoteType = 10; for (auto I = reinterpret_cast<const Elf_Word *>(&Sec[0]), E = I + Sec.size()/4; I != E;) { uint32_t NameSZ = I[0]; @@ -2378,7 +2348,7 @@ template <class ELFT> void ELFDumper<ELFT>::printAMDGPURuntimeMD() { I += alignTo<4>(NameSZ)/4; } - if (Name == "AMD" && Type == RuntimeMDNoteType) { + if (Name == "AMD" && Type == CodeObjectMetadataNoteType) { StringRef Desc(reinterpret_cast<const char *>(I), DescSZ); W.printString(Desc); } @@ -2403,8 +2373,8 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { ArrayRef<uint8_t> StackMapContentsArray = unwrapOrError(Obj->getSectionContents(StackMapSection)); - prettyPrintStackMap(llvm::outs(), StackMapV2Parser<ELFT::TargetEndianness>( - StackMapContentsArray)); + prettyPrintStackMap(outs(), StackMapV2Parser<ELFT::TargetEndianness>( + StackMapContentsArray)); } template <class ELFT> void ELFDumper<ELFT>::printGroupSections() { @@ -2505,7 +2475,7 @@ template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) { template <class ELFT> void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, const Elf_Rela &R, bool IsRela) { - std::string Offset, Info, Addend = "", Value; + std::string Offset, Info, Addend, Value; SmallString<32> RelocName; StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); StringRef TargetName; @@ -2599,6 +2569,7 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { std::string getSectionTypeString(unsigned Arch, unsigned Type) { using namespace ELF; + switch (Arch) { case EM_ARM: switch (Type) { @@ -2627,6 +2598,8 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) { return "MIPS_OPTIONS"; case SHT_MIPS_ABIFLAGS: return "MIPS_ABIFLAGS"; + case SHT_MIPS_DWARF: + return "SHT_MIPS_DWARF"; } } switch (Type) { @@ -2664,6 +2637,8 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) { return "GROUP"; case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICES"; + case SHT_LLVM_ODRTAB: + return "LLVM_ODRTAB"; // FIXME: Parse processor specific GNU attributes case SHT_GNU_ATTRIBUTES: return "ATTRIBUTES"; @@ -2763,7 +2738,7 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { template <class ELFT> void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Entries) { - if (Name.size()) + if (!Name.empty()) OS << "\nSymbol table '" << Name << "' contains " << Entries << " entries:\n"; else @@ -2790,6 +2765,7 @@ std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj, case ELF::SHN_XINDEX: SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( Symbol, FirstSym, this->dumper()->getShndxTable())); + LLVM_FALLTHROUGH; default: // Find if: // Processor specific @@ -2917,7 +2893,7 @@ template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) { template <class ELFT> void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { - if (this->dumper()->getDynamicStringTable().size() == 0) + if (this->dumper()->getDynamicStringTable().empty()) return; auto StringTable = this->dumper()->getDynamicStringTable(); auto DynSyms = this->dumper()->dynamic_symbols(); @@ -3131,19 +3107,19 @@ void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); SymbolName = unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); - std::string Addend = "", Info, Offset, Value; + std::string Addend, Info, Offset, Value; Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); Info = to_string(format_hex_no_prefix(R.r_info, Width)); Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); int64_t RelAddend = R.r_addend; - if (SymbolName.size() && IsRela) { + if (!SymbolName.empty() && IsRela) { if (R.r_addend < 0) Addend = " - "; else Addend = " + "; } - if (!SymbolName.size() && Sym->getValue() == 0) + if (SymbolName.empty() && Sym->getValue() == 0) Value = ""; if (IsRela) @@ -3278,7 +3254,7 @@ void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { size_t MaxChain = 1; size_t CumulativeNonZero = 0; - if (Chains.size() == 0 || NBucket == 0) + if (Chains.empty() || NBucket == 0) return; std::vector<size_t> ChainLen(NBucket, 0); @@ -3337,9 +3313,38 @@ static std::string getGNUNoteTypeName(const uint32_t NT) { return string; } +static std::string getFreeBSDNoteTypeName(const uint32_t NT) { + static const struct { + uint32_t ID; + const char *Name; + } Notes[] = { + {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, + {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, + {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, + {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, + {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, + {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, + {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, + {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, + {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, + "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, + {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, + }; + + 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 string; +} + template <typename ELFT> static void printGNUNote(raw_ostream &OS, uint32_t NoteType, - ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words) { + ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words, + size_t Size) { switch (NoteType) { default: return; @@ -3362,16 +3367,14 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType, } case ELF::NT_GNU_BUILD_ID: { OS << " Build ID: "; - ArrayRef<uint8_t> ID(reinterpret_cast<const uint8_t *>(Words.data()), - Words.size() * 4); + ArrayRef<uint8_t> ID(reinterpret_cast<const uint8_t *>(Words.data()), Size); for (const auto &B : ID) OS << format_hex_no_prefix(B, 2); break; } case ELF::NT_GNU_GOLD_VERSION: OS << " Version: " - << StringRef(reinterpret_cast<const char *>(Words.data()), - Words.size() * 4); + << StringRef(reinterpret_cast<const char *>(Words.data()), Size); break; } @@ -3415,11 +3418,15 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { if (Name == "GNU") { OS << getGNUNoteTypeName(Type) << '\n'; - printGNUNote<ELFT>(OS, Type, Descriptor); + printGNUNote<ELFT>(OS, Type, Descriptor, DescriptorSize); + } else if (Name == "FreeBSD") { + OS << getFreeBSDNoteTypeName(Type) << '\n'; + } else { + OS << "Unknown note type: (" << format_hex(Type, 10) << ')'; } OS << '\n'; - P = P + 3 * sizeof(Elf_Word) * alignTo<4>(NameSize) + + P = P + 3 * sizeof(Elf_Word) + alignTo<4>(NameSize) + alignTo<4>(DescriptorSize); } }; @@ -3578,13 +3585,13 @@ void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel, DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", + W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-", Rel.getSymbol(Obj->isMips64EL())); W.printHex("Addend", Rel.r_addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (TargetName.size() > 0 ? TargetName : "-") << " " + << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -3601,16 +3608,13 @@ template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); W.printNumber("Name", Name, Sec.sh_name); - W.printHex("Type", - getElfSectionType(Obj->getHeader()->e_machine, Sec.sh_type), - Sec.sh_type); + W.printHex( + "Type", + object::getELFSectionTypeName(Obj->getHeader()->e_machine, Sec.sh_type), + Sec.sh_type); std::vector<EnumEntry<unsigned>> SectionFlags(std::begin(ElfSectionFlags), std::end(ElfSectionFlags)); switch (Obj->getHeader()->e_machine) { - case EM_AMDGPU: - SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags), - std::end(ElfAMDGPUSectionFlags)); - break; case EM_ARM: SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), std::end(ElfARMSectionFlags)); @@ -3778,12 +3782,12 @@ void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); W.printHex("Addend", Rel.r_addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (SymbolName.size() > 0 ? SymbolName : "-") << " " + << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -3816,4 +3820,3 @@ template <class ELFT> void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { W.startLine() << "printNotes not implemented!\n"; } - diff --git a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp index 01b0741..39e9092 100644 --- a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp @@ -713,12 +713,30 @@ void MachODumper::printMachOVersionMin() { case MachO::LC_VERSION_MIN_WATCHOS: Cmd = "LC_VERSION_MIN_WATCHOS"; break; + case MachO::LC_BUILD_VERSION: + Cmd = "LC_BUILD_VERSION"; + break; default: continue; } - MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load); DictScope Group(W, "MinVersion"); + // Handle LC_BUILD_VERSION. + if (Load.C.cmd == MachO::LC_BUILD_VERSION) { + MachO::build_version_command BVC = Obj->getBuildVersionLoadCommand(Load); + W.printString("Cmd", Cmd); + W.printNumber("Size", BVC.cmdsize); + W.printString("Platform", + MachOObjectFile::getBuildPlatform(BVC.platform)); + W.printString("Version", MachOObjectFile::getVersionString(BVC.minos)); + if (BVC.sdk) + W.printString("SDK", MachOObjectFile::getVersionString(BVC.sdk)); + else + W.printString("SDK", StringRef("n/a")); + continue; + } + + MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load); W.printString("Cmd", Cmd); W.printNumber("Size", VMC.cmdsize); SmallString<32> Version; diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm/tools/llvm-readobj/ObjDumper.h index c91558e..43883c2 100644 --- a/contrib/llvm/tools/llvm-readobj/ObjDumper.h +++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.h @@ -59,7 +59,7 @@ public: virtual void printMipsOptions() { } // Only implemented for AMDGPU ELF at this time. - virtual void printAMDGPURuntimeMD() {} + virtual void printAMDGPUCodeObjectMetadata() {} // Only implemented for PE/COFF. virtual void printCOFFImports() { } @@ -67,8 +67,11 @@ public: virtual void printCOFFDirectives() { } virtual void printCOFFBaseReloc() { } virtual void printCOFFDebugDirectory() { } + virtual void printCOFFResources() {} + virtual void printCOFFLoadConfig() { } virtual void printCodeViewDebugInfo() { } - virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) {} + virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, + llvm::codeview::TypeTableBuilder &CVTypes) {} // Only implemented for MachO. virtual void printMachODataInCode() { } @@ -96,10 +99,15 @@ std::error_code createMachODumper(const object::ObjectFile *Obj, ScopedPrinter &Writer, std::unique_ptr<ObjDumper> &Result); +std::error_code createWasmDumper(const object::ObjectFile *Obj, + ScopedPrinter &Writer, + std::unique_ptr<ObjDumper> &Result); + void dumpCOFFImportFile(const object::COFFImportFile *File); void dumpCodeViewMergedTypes(ScopedPrinter &Writer, - llvm::codeview::TypeTableBuilder &CVTypes); + llvm::codeview::TypeTableBuilder &IDTable, + llvm::codeview::TypeTableBuilder &TypeTable); } // namespace llvm diff --git a/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp b/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp new file mode 100644 index 0000000..266226d --- /dev/null +++ b/contrib/llvm/tools/llvm-readobj/WasmDumper.cpp @@ -0,0 +1,209 @@ +//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Wasm-specific dumper for llvm-readobj. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "ObjDumper.h" +#include "llvm-readobj.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace llvm; +using namespace object; + +namespace { + +static const EnumEntry<unsigned> WasmSymbolTypes[] = { +#define ENUM_ENTRY(X) { #X, static_cast<unsigned>(WasmSymbol::SymbolType::X) } + ENUM_ENTRY(FUNCTION_IMPORT), + ENUM_ENTRY(FUNCTION_EXPORT), + ENUM_ENTRY(GLOBAL_IMPORT), + ENUM_ENTRY(GLOBAL_EXPORT), + ENUM_ENTRY(DEBUG_FUNCTION_NAME), +#undef ENUM_ENTRY +}; + +static const EnumEntry<uint32_t> WasmSectionTypes[] = { +#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X } + ENUM_ENTRY(CUSTOM), + ENUM_ENTRY(TYPE), + ENUM_ENTRY(IMPORT), + ENUM_ENTRY(FUNCTION), + ENUM_ENTRY(TABLE), + ENUM_ENTRY(MEMORY), + ENUM_ENTRY(GLOBAL), + ENUM_ENTRY(EXPORT), + ENUM_ENTRY(START), + ENUM_ENTRY(ELEM), + ENUM_ENTRY(CODE), + ENUM_ENTRY(DATA), +#undef ENUM_ENTRY +}; + +class WasmDumper : public ObjDumper { +public: + WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer) + : ObjDumper(Writer), Obj(Obj) {} + + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override { llvm_unreachable("unimplemented"); } + void printUnwindInfo() override { llvm_unreachable("unimplemented"); } + void printStackMap() const override { llvm_unreachable("unimplemented"); } + +protected: + void printSymbol(const SymbolRef &Sym); + void printRelocation(const SectionRef &Section, const RelocationRef &Reloc); + +private: + const WasmObjectFile *Obj; +}; + +void WasmDumper::printFileHeaders() { + W.printHex("Version", Obj->getHeader().Version); +} + +void WasmDumper::printRelocation(const SectionRef &Section, + const RelocationRef &Reloc) { + SmallString<64> RelocTypeName; + uint64_t RelocType = Reloc.getType(); + Reloc.getTypeName(RelocTypeName); + const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc); + + bool HasAddend = false; + switch (RelocType) { + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + HasAddend = true; + break; + default: + break; + } + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printNumber("Type", RelocTypeName, RelocType); + W.printHex("Offset", Reloc.getOffset()); + W.printHex("Index", WasmReloc.Index); + if (HasAddend) + W.printNumber("Addend", WasmReloc.Addend); + } else { + raw_ostream& OS = W.startLine(); + OS << W.hex(Reloc.getOffset()) + << " " << RelocTypeName << "[" << WasmReloc.Index << "]"; + if (HasAddend) + OS << " " << WasmReloc.Addend; + OS << "\n"; + } +} + +void WasmDumper::printRelocations() { + ListScope D(W, "Relocations"); + + int SectionNumber = 0; + for (const SectionRef &Section : Obj->sections()) { + bool PrintedGroup = false; + StringRef Name; + error(Section.getName(Name)); + ++SectionNumber; + + for (const RelocationRef &Reloc : Section.relocations()) { + if (!PrintedGroup) { + W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; + W.indent(); + PrintedGroup = true; + } + + printRelocation(Section, Reloc); + } + + if (PrintedGroup) { + W.unindent(); + W.startLine() << "}\n"; + } + } +} + +void WasmDumper::printSymbols() { + ListScope Group(W, "Symbols"); + + for (const SymbolRef &Symbol : Obj->symbols()) + printSymbol(Symbol); +} + +void WasmDumper::printSections() { + ListScope Group(W, "Sections"); + for (const SectionRef &Section : Obj->sections()) { + const WasmSection &WasmSec = Obj->getWasmSection(Section); + DictScope SectionD(W, "Section"); + W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes)); + W.printNumber("Size", (uint64_t)WasmSec.Content.size()); + W.printNumber("Offset", WasmSec.Offset); + switch (WasmSec.Type) { + case wasm::WASM_SEC_CUSTOM: + W.printString("Name", WasmSec.Name); + if (WasmSec.Name == "linking") { + const wasm::WasmLinkingData &LinkingData = Obj->linkingData(); + W.printNumber("DataSize", LinkingData.DataSize); + if (LinkingData.DataAlignment) + W.printNumber("DataAlignment", LinkingData.DataAlignment); + } + break; + case wasm::WASM_SEC_MEMORY: + ListScope Group(W, "Memories"); + for (const wasm::WasmLimits &Memory : Obj->memories()) { + DictScope Group(W, "Memory"); + W.printNumber("InitialPages", Memory.Initial); + if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) { + W.printNumber("MaxPages", WasmSec.Offset); + } + } + break; + } + + if (opts::SectionRelocations) { + ListScope D(W, "Relocations"); + for (const RelocationRef &Reloc : Section.relocations()) + printRelocation(Section, Reloc); + } + + if (opts::SectionData) { + W.printBinaryBlock("SectionData", WasmSec.Content); + } + } +} + +void WasmDumper::printSymbol(const SymbolRef &Sym) { + DictScope D(W, "Symbol"); + WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl()); + W.printString("Name", Symbol.Name); + W.printEnum("Type", static_cast<unsigned>(Symbol.Type), makeArrayRef(WasmSymbolTypes)); + W.printHex("Flags", Symbol.Flags); +} + +} + +namespace llvm { + +std::error_code createWasmDumper(const object::ObjectFile *Obj, + ScopedPrinter &Writer, + std::unique_ptr<ObjDumper> &Result) { + const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj); + assert(WasmObj && "createWasmDumper called with non-wasm object"); + + Result.reset(new WasmDumper(WasmObj, Writer)); + return readobj_error::success; +} + +} // namespace llvm diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp index 970e154..7bfb18f 100644 --- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/Signals.h" @@ -50,6 +51,13 @@ namespace opts { cl::desc("<input object files>"), cl::ZeroOrMore); + // -wide, -W + cl::opt<bool> WideOutput("wide", + cl::desc("Ignored for compatibility with GNU readelf")); + cl::alias WideOutputShort("W", + cl::desc("Alias for --wide"), + cl::aliasopt(WideOutput)); + // -file-headers, -h cl::opt<bool> FileHeaders("file-headers", cl::desc("Display file headers ")); @@ -57,12 +65,16 @@ namespace opts { cl::desc("Alias for --file-headers"), cl::aliasopt(FileHeaders)); - // -sections, -s + // -sections, -s, -S + // Note: In GNU readelf, -s means --symbols! cl::opt<bool> Sections("sections", cl::desc("Display all sections.")); cl::alias SectionsShort("s", cl::desc("Alias for --sections"), cl::aliasopt(Sections)); + cl::alias SectionsShortUpper("S", + cl::desc("Alias for --sections"), + cl::aliasopt(Sections)); // -section-relocations, -sr cl::opt<bool> SectionRelocations("section-relocations", @@ -186,9 +198,10 @@ namespace opts { cl::opt<bool> MipsOptions("mips-options", cl::desc("Display the MIPS .MIPS.options section")); - // -amdgpu-runtime-metadata - cl::opt<bool> AMDGPURuntimeMD("amdgpu-runtime-metadata", - cl::desc("Display AMDGPU runtime metadata")); + // -amdgpu-code-object-metadata + cl::opt<bool> AMDGPUCodeObjectMetadata( + "amdgpu-code-object-metadata", + cl::desc("Display AMDGPU code object metadata")); // -coff-imports cl::opt<bool> @@ -213,6 +226,15 @@ namespace opts { COFFDebugDirectory("coff-debug-directory", cl::desc("Display the PE/COFF debug directory")); + // -coff-resources + cl::opt<bool> COFFResources("coff-resources", + cl::desc("Display the PE/COFF .rsrc section")); + + // -coff-load-config + cl::opt<bool> + COFFLoadConfig("coff-load-config", + cl::desc("Display the PE/COFF load config")); + // -macho-data-in-code cl::opt<bool> MachODataInCode("macho-data-in-code", @@ -306,13 +328,6 @@ static void reportError(StringRef Input, std::error_code EC) { reportError(Twine(Input) + ": " + EC.message()); } -static void reportError(StringRef Input, StringRef Message) { - if (Input == "-") - Input = "<stdin>"; - - reportError(Twine(Input) + ": " + Message); -} - static void reportError(StringRef Input, Error Err) { if (Input == "-") Input = "<stdin>"; @@ -337,10 +352,12 @@ static bool isMipsArch(unsigned Arch) { } namespace { struct ReadObjTypeTableBuilder { - ReadObjTypeTableBuilder() : Allocator(), Builder(Allocator) {} + ReadObjTypeTableBuilder() + : Allocator(), IDTable(Allocator), TypeTable(Allocator) {} llvm::BumpPtrAllocator Allocator; - llvm::codeview::TypeTableBuilder Builder; + llvm::codeview::TypeTableBuilder IDTable; + llvm::codeview::TypeTableBuilder TypeTable; }; } static ReadObjTypeTableBuilder CVTypes; @@ -358,6 +375,8 @@ static std::error_code createDumper(const ObjectFile *Obj, return createELFDumper(Obj, Writer, Result); if (Obj->isMachO()) return createMachODumper(Obj, Writer, Result); + if (Obj->isWasm()) + return createWasmDumper(Obj, Writer, Result); return readobj_error::unsupported_obj_file_format; } @@ -420,8 +439,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printMipsOptions(); } if (Obj->getArch() == llvm::Triple::amdgcn) - if (opts::AMDGPURuntimeMD) - Dumper->printAMDGPURuntimeMD(); + if (opts::AMDGPUCodeObjectMetadata) + Dumper->printAMDGPUCodeObjectMetadata(); if (opts::SectionGroups) Dumper->printGroupSections(); if (opts::HashHistogram) @@ -440,10 +459,14 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printCOFFBaseReloc(); if (opts::COFFDebugDirectory) Dumper->printCOFFDebugDirectory(); + if (opts::COFFResources) + Dumper->printCOFFResources(); + if (opts::COFFLoadConfig) + Dumper->printCOFFLoadConfig(); if (opts::CodeView) Dumper->printCodeViewDebugInfo(); if (opts::CodeViewMergedTypes) - Dumper->mergeCodeViewTypes(CVTypes.Builder); + Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable); } if (Obj->isMachO()) { if (opts::MachODataInCode) @@ -470,11 +493,7 @@ static void dumpArchive(const Archive *Arc) { Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); if (!ChildOrErr) { if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(ChildOrErr.takeError(), OS, ""); - OS.flush(); - reportError(Arc->getFileName(), Buf); + reportError(Arc->getFileName(), ChildOrErr.takeError()); } continue; } @@ -496,11 +515,7 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) { if (ObjOrErr) dumpObject(&*ObjOrErr.get()); else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(ObjOrErr.takeError(), OS, ""); - OS.flush(); - reportError(UBinary->getFileName(), Buf); + reportError(UBinary->getFileName(), ObjOrErr.takeError()); } else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive()) dumpArchive(&*AOrErr.get()); @@ -513,7 +528,7 @@ static void dumpInput(StringRef File) { // Attempt to open the binary. Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File); if (!BinaryOrErr) - reportError(File, errorToErrorCode(BinaryOrErr.takeError())); + reportError(File, BinaryOrErr.takeError()); Binary &Binary = *BinaryOrErr.get().getBinary(); if (Archive *Arc = dyn_cast<Archive>(&Binary)) @@ -530,13 +545,19 @@ static void dumpInput(StringRef File) { } int main(int argc, const char *argv[]) { - sys::PrintStackTraceOnErrorSignal(argv[0]); + StringRef ToolName = argv[0]; + sys::PrintStackTraceOnErrorSignal(ToolName); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + opts::WideOutput.setHiddenFlag(cl::Hidden); + + if (sys::path::stem(ToolName).find("readelf") != StringRef::npos) + opts::Output = opts::GNU; + cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n"); // Default to stdin if no filename is specified. @@ -548,7 +569,7 @@ int main(int argc, const char *argv[]) { if (opts::CodeViewMergedTypes) { ScopedPrinter W(outs()); - dumpCodeViewMergedTypes(W, CVTypes.Builder); + dumpCodeViewMergedTypes(W, CVTypes.IDTable, CVTypes.TypeTable); } return 0; diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h index 0156920..840ddba 100644 --- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h +++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h @@ -25,6 +25,11 @@ namespace llvm { LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg); void error(std::error_code EC); void error(llvm::Error EC); + template <typename T> T error(llvm::Expected<T> &&E) { + error(E.takeError()); + return std::move(*E); + } + template <class T> T unwrapOrError(ErrorOr<T> EO) { if (EO) return *EO; |