diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/BinaryFormat | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/BinaryFormat')
-rw-r--r-- | llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/Dwarf.cpp | 33 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/MachO.cpp | 109 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/Magic.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/MsgPackDocument.cpp | 122 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/Wasm.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/XCOFF.cpp | 80 |
7 files changed, 306 insertions, 65 deletions
diff --git a/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp b/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp index d927171d556ce..cd1d872cc2194 100644 --- a/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp +++ b/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/AMDGPUMetadata.h" namespace llvm { @@ -126,25 +127,6 @@ bool MetadataVerifier::verifyKernelArgs(msgpack::DocNode &Node) { .Default(false); })) return false; - if (!verifyScalarEntry(ArgsMap, ".value_type", true, - msgpack::Type::String, - [](msgpack::DocNode &SNode) { - return StringSwitch<bool>(SNode.getString()) - .Case("struct", true) - .Case("i8", true) - .Case("u8", true) - .Case("i16", true) - .Case("u16", true) - .Case("f16", true) - .Case("i32", true) - .Case("u32", true) - .Case("f32", true) - .Case("i64", true) - .Case("u64", true) - .Case("f64", true) - .Default(false); - })) - return false; if (!verifyIntegerEntry(ArgsMap, ".pointee_align", false)) return false; if (!verifyScalarEntry(ArgsMap, ".address_space", false, diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp index 9ca3317418ce3..a497c16685c1a 100644 --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -477,6 +477,23 @@ unsigned llvm::dwarf::getMacinfo(StringRef MacinfoString) { .Default(DW_MACINFO_invalid); } +StringRef llvm::dwarf::MacroString(unsigned Encoding) { + switch (Encoding) { + default: + return StringRef(); +#define HANDLE_DW_MACRO(ID, NAME) \ + case DW_MACRO_##NAME: \ + return "DW_MACRO_" #NAME; +#include "llvm/BinaryFormat/Dwarf.def" + } +} + +unsigned llvm::dwarf::getMacro(StringRef MacroString) { + return StringSwitch<unsigned>(MacroString) +#define HANDLE_DW_MACRO(ID, NAME) .Case("DW_MACRO_" #NAME, ID) +#include "llvm/BinaryFormat/Dwarf.def" + .Default(DW_MACINFO_invalid); +} StringRef llvm::dwarf::RangeListEncodingString(unsigned Encoding) { switch (Encoding) { default: @@ -753,7 +770,23 @@ bool llvm::dwarf::isValidFormForVersion(Form F, unsigned Version, return ExtensionsOk; } +StringRef llvm::dwarf::FormatString(DwarfFormat Format) { + switch (Format) { + case DWARF32: + return "DWARF32"; + case DWARF64: + return "DWARF64"; + } + return StringRef(); +} + +StringRef llvm::dwarf::FormatString(bool IsDWARF64) { + return FormatString(IsDWARF64 ? DWARF64 : DWARF32); +} + constexpr char llvm::dwarf::EnumTraits<Attribute>::Type[]; constexpr char llvm::dwarf::EnumTraits<Form>::Type[]; constexpr char llvm::dwarf::EnumTraits<Index>::Type[]; constexpr char llvm::dwarf::EnumTraits<Tag>::Type[]; +constexpr char llvm::dwarf::EnumTraits<LineNumberOps>::Type[]; +constexpr char llvm::dwarf::EnumTraits<LocationAtom>::Type[]; diff --git a/llvm/lib/BinaryFormat/MachO.cpp b/llvm/lib/BinaryFormat/MachO.cpp new file mode 100644 index 0000000000000..2b9eb80255219 --- /dev/null +++ b/llvm/lib/BinaryFormat/MachO.cpp @@ -0,0 +1,109 @@ +//===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ARMTargetParser.h" + +using namespace llvm; + +static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) { + assert(T.isX86()); + if (T.isArch32Bit()) + return MachO::CPU_SUBTYPE_I386_ALL; + + assert(T.isArch64Bit()); + if (T.getArchName() == "x86_64h") + return MachO::CPU_SUBTYPE_X86_64_H; + return MachO::CPU_SUBTYPE_X86_64_ALL; +} + +static MachO::CPUSubTypeARM getARMSubType(const Triple &T) { + assert(T.isARM() || T.isThumb()); + StringRef Arch = T.getArchName(); + ARM::ArchKind AK = ARM::parseArch(Arch); + switch (AK) { + default: + return MachO::CPU_SUBTYPE_ARM_V7; + case ARM::ArchKind::ARMV4T: + return MachO::CPU_SUBTYPE_ARM_V4T; + case ARM::ArchKind::ARMV5T: + case ARM::ArchKind::ARMV5TE: + case ARM::ArchKind::ARMV5TEJ: + return MachO::CPU_SUBTYPE_ARM_V5; + case ARM::ArchKind::ARMV6: + case ARM::ArchKind::ARMV6K: + return MachO::CPU_SUBTYPE_ARM_V6; + case ARM::ArchKind::ARMV7A: + return MachO::CPU_SUBTYPE_ARM_V7; + case ARM::ArchKind::ARMV7S: + return MachO::CPU_SUBTYPE_ARM_V7S; + case ARM::ArchKind::ARMV7K: + return MachO::CPU_SUBTYPE_ARM_V7K; + case ARM::ArchKind::ARMV6M: + return MachO::CPU_SUBTYPE_ARM_V6M; + case ARM::ArchKind::ARMV7M: + return MachO::CPU_SUBTYPE_ARM_V7M; + case ARM::ArchKind::ARMV7EM: + return MachO::CPU_SUBTYPE_ARM_V7EM; + } +} + +static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) { + assert(T.isAArch64() || T.getArch() == Triple::aarch64_32); + if (T.isArch32Bit()) + return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8; + if (T.getArchName() == "arm64e") + return MachO::CPU_SUBTYPE_ARM64E; + + return MachO::CPU_SUBTYPE_ARM64_ALL; +} + +static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) { + return MachO::CPU_SUBTYPE_POWERPC_ALL; +} + +static Error unsupported(const char *Str, const Triple &T) { + return createStringError(std::errc::invalid_argument, + "Unsupported triple for mach-o cpu %s: %s", Str, + T.str().c_str()); +} + +Expected<uint32_t> MachO::getCPUType(const Triple &T) { + if (!T.isOSBinFormatMachO()) + return unsupported("type", T); + if (T.isX86() && T.isArch32Bit()) + return MachO::CPU_TYPE_X86; + if (T.isX86() && T.isArch64Bit()) + return MachO::CPU_TYPE_X86_64; + if (T.isARM() || T.isThumb()) + return MachO::CPU_TYPE_ARM; + if (T.isAArch64()) + return MachO::CPU_TYPE_ARM64; + if (T.getArch() == Triple::aarch64_32) + return MachO::CPU_TYPE_ARM64_32; + if (T.getArch() == Triple::ppc) + return MachO::CPU_TYPE_POWERPC; + if (T.getArch() == Triple::ppc64) + return MachO::CPU_TYPE_POWERPC64; + return unsupported("type", T); +} + +Expected<uint32_t> MachO::getCPUSubType(const Triple &T) { + if (!T.isOSBinFormatMachO()) + return unsupported("subtype", T); + if (T.isX86()) + return getX86SubType(T); + if (T.isARM() || T.isThumb()) + return getARMSubType(T); + if (T.isAArch64() || T.getArch() == Triple::aarch64_32) + return getARM64SubType(T); + if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64) + return getPowerPCSubType(T); + return unsupported("subtype", T); +} diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp index bbcbbabededbe..61b1504e59b0a 100644 --- a/llvm/lib/BinaryFormat/Magic.cpp +++ b/llvm/lib/BinaryFormat/Magic.cpp @@ -7,7 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/BinaryFormat/Magic.h" - +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" diff --git a/llvm/lib/BinaryFormat/MsgPackDocument.cpp b/llvm/lib/BinaryFormat/MsgPackDocument.cpp index e12c54a37ad0b..53720c542e14d 100644 --- a/llvm/lib/BinaryFormat/MsgPackDocument.cpp +++ b/llvm/lib/BinaryFormat/MsgPackDocument.cpp @@ -40,46 +40,100 @@ DocNode &MapDocNode::operator[](StringRef S) { /// Member access for MapDocNode. DocNode &MapDocNode::operator[](DocNode Key) { assert(!Key.isEmpty()); - MapTy::value_type Entry(Key, DocNode()); - auto ItAndInserted = Map->insert(Entry); - if (ItAndInserted.second) { + DocNode &N = (*Map)[Key]; + if (N.isEmpty()) { // Ensure a new element has its KindAndDoc initialized. - ItAndInserted.first->second = getDocument()->getNode(); + N = getDocument()->getEmptyNode(); } - return ItAndInserted.first->second; + return N; +} + +/// Member access for MapDocNode for integer key. +DocNode &MapDocNode::operator[](int Key) { + return (*this)[getDocument()->getNode(Key)]; +} +DocNode &MapDocNode::operator[](unsigned Key) { + return (*this)[getDocument()->getNode(Key)]; +} +DocNode &MapDocNode::operator[](int64_t Key) { + return (*this)[getDocument()->getNode(Key)]; +} +DocNode &MapDocNode::operator[](uint64_t Key) { + return (*this)[getDocument()->getNode(Key)]; } /// Array element access. This extends the array if necessary. DocNode &ArrayDocNode::operator[](size_t Index) { if (size() <= Index) { // Ensure new elements have their KindAndDoc initialized. - Array->resize(Index + 1, getDocument()->getNode()); + Array->resize(Index + 1, getDocument()->getEmptyNode()); } return (*Array)[Index]; } +// Convenience assignment operators. This only works if the destination +// DocNode has an associated Document, i.e. it was not constructed using the +// default constructor. The string one does not copy, so the string must +// remain valid for the lifetime of the Document. Use fromString to avoid +// that restriction. +DocNode &DocNode::operator=(StringRef Val) { + *this = getDocument()->getNode(Val); + return *this; +} +DocNode &DocNode::operator=(bool Val) { + *this = getDocument()->getNode(Val); + return *this; +} +DocNode &DocNode::operator=(int Val) { + *this = getDocument()->getNode(Val); + return *this; +} +DocNode &DocNode::operator=(unsigned Val) { + *this = getDocument()->getNode(Val); + return *this; +} +DocNode &DocNode::operator=(int64_t Val) { + *this = getDocument()->getNode(Val); + return *this; +} +DocNode &DocNode::operator=(uint64_t Val) { + *this = getDocument()->getNode(Val); + return *this; +} + // A level in the document reading stack. struct StackLevel { + StackLevel(DocNode Node, size_t StartIndex, size_t Length, + DocNode *MapEntry = nullptr) + : Node(Node), Index(StartIndex), End(StartIndex + Length), + MapEntry(MapEntry) {} DocNode Node; - size_t Length; + size_t Index; + size_t End; // Points to map entry when we have just processed a map key. DocNode *MapEntry; + DocNode MapKey; }; -// Read a document from a binary msgpack blob. +// Read a document from a binary msgpack blob, merging into anything already in +// the Document. // The blob data must remain valid for the lifetime of this Document (because a // string object in the document contains a StringRef into the original blob). // If Multi, then this sets root to an array and adds top-level objects to it. // If !Multi, then it only reads a single top-level object, even if there are // more, and sets root to that. -// Returns false if failed due to illegal format. -bool Document::readFromBlob(StringRef Blob, bool Multi) { +// Returns false if failed due to illegal format or merge error. + +bool Document::readFromBlob( + StringRef Blob, bool Multi, + function_ref<int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)> + Merger) { msgpack::Reader MPReader(Blob); SmallVector<StackLevel, 4> Stack; if (Multi) { // Create the array for multiple top-level objects. Root = getArrayNode(); - Stack.push_back(StackLevel({Root, (size_t)-1, nullptr})); + Stack.push_back(StackLevel(Root, 0, (size_t)-1)); } do { // On to next element (or key if doing a map key next). @@ -124,29 +178,47 @@ bool Document::readFromBlob(StringRef Blob, bool Multi) { } // Store it. + DocNode *DestNode = nullptr; if (Stack.empty()) - Root = Node; + DestNode = &Root; else if (Stack.back().Node.getKind() == Type::Array) { // Reading an array entry. auto &Array = Stack.back().Node.getArray(); - Array.push_back(Node); + DestNode = &Array[Stack.back().Index++]; } else { auto &Map = Stack.back().Node.getMap(); if (!Stack.back().MapEntry) { // Reading a map key. + Stack.back().MapKey = Node; Stack.back().MapEntry = &Map[Node]; - } else { - // Reading the value for the map key read in the last iteration. - *Stack.back().MapEntry = Node; - Stack.back().MapEntry = nullptr; + continue; } + // Reading the value for the map key read in the last iteration. + DestNode = Stack.back().MapEntry; + Stack.back().MapEntry = nullptr; + ++Stack.back().Index; } + int MergeResult = 0; + if (!DestNode->isEmpty()) { + // In a merge, there is already a value at this position. Call the + // callback to attempt to resolve the conflict. The resolution must result + // in an array or map if Node is an array or map respectively. + DocNode MapKey = !Stack.empty() && !Stack.back().MapKey.isEmpty() + ? Stack.back().MapKey + : getNode(); + MergeResult = Merger(DestNode, Node, MapKey); + if (MergeResult < 0) + return false; // Merge conflict resolution failed + assert(!((Node.isMap() && !DestNode->isMap()) || + (Node.isArray() && !DestNode->isArray()))); + } else + *DestNode = Node; // See if we're starting a new array or map. - switch (Node.getKind()) { + switch (DestNode->getKind()) { case msgpack::Type::Array: case msgpack::Type::Map: - Stack.push_back(StackLevel({Node, Obj.Length, nullptr})); + Stack.push_back(StackLevel(*DestNode, MergeResult, Obj.Length, nullptr)); break; default: break; @@ -154,14 +226,10 @@ bool Document::readFromBlob(StringRef Blob, bool Multi) { // Pop finished stack levels. while (!Stack.empty()) { - if (Stack.back().Node.getKind() == msgpack::Type::Array) { - if (Stack.back().Node.getArray().size() != Stack.back().Length) - break; - } else { - if (Stack.back().MapEntry || - Stack.back().Node.getMap().size() != Stack.back().Length) - break; - } + if (Stack.back().MapEntry) + break; + if (Stack.back().Index != Stack.back().End) + break; Stack.pop_back(); } } while (!Stack.empty()); diff --git a/llvm/lib/BinaryFormat/Wasm.cpp b/llvm/lib/BinaryFormat/Wasm.cpp index d46be481edb36..88608168783b0 100644 --- a/llvm/lib/BinaryFormat/Wasm.cpp +++ b/llvm/lib/BinaryFormat/Wasm.cpp @@ -39,9 +39,13 @@ std::string llvm::wasm::relocTypetoString(uint32_t Type) { bool llvm::wasm::relocTypeHasAddend(uint32_t Type) { switch (Type) { case R_WASM_MEMORY_ADDR_LEB: + case R_WASM_MEMORY_ADDR_LEB64: case R_WASM_MEMORY_ADDR_SLEB: + case R_WASM_MEMORY_ADDR_SLEB64: case R_WASM_MEMORY_ADDR_REL_SLEB: + case R_WASM_MEMORY_ADDR_REL_SLEB64: case R_WASM_MEMORY_ADDR_I32: + case R_WASM_MEMORY_ADDR_I64: case R_WASM_FUNCTION_OFFSET_I32: case R_WASM_SECTION_OFFSET_I32: return true; diff --git a/llvm/lib/BinaryFormat/XCOFF.cpp b/llvm/lib/BinaryFormat/XCOFF.cpp index 29ccbaea3584d..3c8a2cdbc3aae 100644 --- a/llvm/lib/BinaryFormat/XCOFF.cpp +++ b/llvm/lib/BinaryFormat/XCOFF.cpp @@ -7,28 +7,72 @@ //===----------------------------------------------------------------------===// #include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; +#define SMC_CASE(A) \ + case XCOFF::XMC_##A: \ + return #A; StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) { switch (SMC) { - case XCOFF::XMC_DS: - return "DS"; - case XCOFF::XMC_RW: - return "RW"; - case XCOFF::XMC_PR: - return "PR"; - case XCOFF::XMC_TC0: - return "TC0"; - case XCOFF::XMC_BS: - return "BS"; - case XCOFF::XMC_RO: - return "RO"; - case XCOFF::XMC_UA: - return "UA"; - case XCOFF::XMC_TC: - return "TC"; - default: - report_fatal_error("Unhandled storage-mapping class."); + SMC_CASE(PR) + SMC_CASE(RO) + SMC_CASE(DB) + SMC_CASE(GL) + SMC_CASE(XO) + SMC_CASE(SV) + SMC_CASE(SV64) + SMC_CASE(SV3264) + SMC_CASE(TI) + SMC_CASE(TB) + SMC_CASE(RW) + SMC_CASE(TC0) + SMC_CASE(TC) + SMC_CASE(TD) + SMC_CASE(DS) + SMC_CASE(UA) + SMC_CASE(BS) + SMC_CASE(UC) + SMC_CASE(TL) + SMC_CASE(UL) + SMC_CASE(TE) +#undef SMC_CASE } + + // TODO: need to add a test case for "Unknown" and other SMC. + return "Unknown"; +} + +#define RELOC_CASE(A) \ + case XCOFF::A: \ + return #A; +StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) { + switch (Type) { + RELOC_CASE(R_POS) + RELOC_CASE(R_RL) + RELOC_CASE(R_RLA) + RELOC_CASE(R_NEG) + RELOC_CASE(R_REL) + RELOC_CASE(R_TOC) + RELOC_CASE(R_TRL) + RELOC_CASE(R_TRLA) + RELOC_CASE(R_GL) + RELOC_CASE(R_TCL) + RELOC_CASE(R_REF) + RELOC_CASE(R_BA) + RELOC_CASE(R_BR) + RELOC_CASE(R_RBA) + RELOC_CASE(R_RBR) + RELOC_CASE(R_TLS) + RELOC_CASE(R_TLS_IE) + RELOC_CASE(R_TLS_LD) + RELOC_CASE(R_TLS_LE) + RELOC_CASE(R_TLSM) + RELOC_CASE(R_TLSML) + RELOC_CASE(R_TOCU) + RELOC_CASE(R_TOCL) + } + return "Unknown"; } +#undef RELOC_CASE |