summaryrefslogtreecommitdiff
path: root/llvm/lib/BinaryFormat
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/BinaryFormat
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/lib/BinaryFormat')
-rw-r--r--llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp20
-rw-r--r--llvm/lib/BinaryFormat/Dwarf.cpp33
-rw-r--r--llvm/lib/BinaryFormat/MachO.cpp109
-rw-r--r--llvm/lib/BinaryFormat/Magic.cpp3
-rw-r--r--llvm/lib/BinaryFormat/MsgPackDocument.cpp122
-rw-r--r--llvm/lib/BinaryFormat/Wasm.cpp4
-rw-r--r--llvm/lib/BinaryFormat/XCOFF.cpp80
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