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