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/File.h" 11 #include "lld/Core/Reader.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/Support/Errc.h" 14 #include "llvm/Support/FileUtilities.h" 15 #include "llvm/Support/MemoryBuffer.h" 16 #include <memory> 17 #include <system_error> 18 19 namespace lld { 20 21 YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() {} 22 23 void Registry::add(std::unique_ptr<Reader> reader) { 24 _readers.push_back(std::move(reader)); 25 } 26 27 void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) { 28 _yamlHandlers.push_back(std::move(handler)); 29 } 30 31 ErrorOr<std::unique_ptr<File>> 32 Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const { 33 // Get file magic. 34 StringRef content(mb->getBufferStart(), mb->getBufferSize()); 35 llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content); 36 37 // Ask each registered reader if it can handle this file type or extension. 38 for (const std::unique_ptr<Reader> &reader : _readers) { 39 if (!reader->canParse(fileType, mb->getMemBufferRef())) 40 continue; 41 return reader->loadFile(std::move(mb), *this); 42 } 43 44 // No Reader could parse this file. 45 return make_error_code(llvm::errc::executable_format_error); 46 } 47 48 static const Registry::KindStrings kindStrings[] = { 49 {Reference::kindLayoutAfter, "layout-after"}, 50 {Reference::kindAssociate, "associate"}, 51 LLD_KIND_STRING_END}; 52 53 Registry::Registry() { 54 addKindTable(Reference::KindNamespace::all, Reference::KindArch::all, 55 kindStrings); 56 } 57 58 bool Registry::handleTaggedDoc(llvm::yaml::IO &io, 59 const lld::File *&file) const { 60 for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers) 61 if (h->handledDocTag(io, file)) 62 return true; 63 return false; 64 } 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