1//===- lib/Core/Reader.cpp ------------------------------------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lld/Core/Reader.h" 10#include "lld/Core/File.h" 11#include "lld/Core/Reference.h" 12#include "llvm/ADT/StringRef.h" 13#include "llvm/BinaryFormat/Magic.h" 14#include "llvm/Support/Errc.h" 15#include "llvm/Support/FileSystem.h" 16#include "llvm/Support/MemoryBuffer.h" 17#include <algorithm> 18#include <memory> 19 20using llvm::file_magic; 21using llvm::identify_magic; 22 23namespace lld { 24 25YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() = default; 26 27void Registry::add(std::unique_ptr<Reader> reader) { 28 _readers.push_back(std::move(reader)); 29} 30 31void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) { 32 _yamlHandlers.push_back(std::move(handler)); 33} 34 35ErrorOr<std::unique_ptr<File>> 36Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const { 37 // Get file magic. 38 StringRef content(mb->getBufferStart(), mb->getBufferSize()); 39 file_magic fileType = identify_magic(content); 40 41 // Ask each registered reader if it can handle this file type or extension. 42 for (const std::unique_ptr<Reader> &reader : _readers) { 43 if (!reader->canParse(fileType, mb->getMemBufferRef())) 44 continue; 45 return reader->loadFile(std::move(mb), *this); 46 } 47 48 // No Reader could parse this file. 49 return make_error_code(llvm::errc::executable_format_error); 50} 51 52static const Registry::KindStrings kindStrings[] = { 53 {Reference::kindLayoutAfter, "layout-after"}, 54 {Reference::kindAssociate, "associate"}, 55 LLD_KIND_STRING_END}; 56 57Registry::Registry() { 58 addKindTable(Reference::KindNamespace::all, Reference::KindArch::all, 59 kindStrings); 60} 61 62bool Registry::handleTaggedDoc(llvm::yaml::IO &io, 63 const lld::File *&file) const { 64 for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers) 65 if (h->handledDocTag(io, file)) 66 return true; 67 return false; 68} 69 70void Registry::addKindTable(Reference::KindNamespace ns, 71 Reference::KindArch arch, 72 const KindStrings array[]) { 73 KindEntry entry = { ns, arch, array }; 74 _kindEntries.push_back(entry); 75} 76 77bool Registry::referenceKindFromString(StringRef inputStr, 78 Reference::KindNamespace &ns, 79 Reference::KindArch &arch, 80 Reference::KindValue &value) const { 81 for (const KindEntry &entry : _kindEntries) { 82 for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) { 83 if (!inputStr.equals(pair->name)) 84 continue; 85 ns = entry.ns; 86 arch = entry.arch; 87 value = pair->value; 88 return true; 89 } 90 } 91 return false; 92} 93 94bool Registry::referenceKindToString(Reference::KindNamespace ns, 95 Reference::KindArch arch, 96 Reference::KindValue value, 97 StringRef &str) const { 98 for (const KindEntry &entry : _kindEntries) { 99 if (entry.ns != ns) 100 continue; 101 if (entry.arch != arch) 102 continue; 103 for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) { 104 if (pair->value != value) 105 continue; 106 str = pair->name; 107 return true; 108 } 109 } 110 return false; 111} 112 113} // end namespace lld 114