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