1 //===- lld/Core/Reader.h - Abstract File Format Reading Interface ---------===// 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 #ifndef LLD_CORE_READER_H 10 #define LLD_CORE_READER_H 11 12 #include "lld/Common/LLVM.h" 13 #include "lld/Core/Reference.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/BinaryFormat/Magic.h" 16 #include "llvm/Support/ErrorOr.h" 17 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include <memory> 20 #include <vector> 21 22 namespace llvm { 23 namespace yaml { 24 class IO; 25 } // end namespace yaml 26 } // end namespace llvm 27 28 namespace lld { 29 30 class File; 31 class LinkingContext; 32 class MachOLinkingContext; 33 34 /// An abstract class for reading object files, library files, and 35 /// executable files. 36 /// 37 /// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader. 38 class Reader { 39 public: 40 virtual ~Reader() = default; 41 42 /// Sniffs the file to determine if this Reader can parse it. 43 /// The method is called with: 44 /// 1) the file_magic enumeration returned by identify_magic() 45 /// 2) the whole file content buffer if the above is not enough. 46 virtual bool canParse(llvm::file_magic magic, MemoryBufferRef mb) const = 0; 47 48 /// Parse a supplied buffer (already filled with the contents of a 49 /// file) and create a File object. 50 /// The resulting File object takes ownership of the MemoryBuffer. 51 virtual ErrorOr<std::unique_ptr<File>> 52 loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &) const = 0; 53 }; 54 55 /// An abstract class for handling alternate yaml representations 56 /// of object files. 57 /// 58 /// The YAML syntax allows "tags" which are used to specify the type of 59 /// the YAML node. In lld, top level YAML documents can be in many YAML 60 /// representations (e.g mach-o encoded as yaml, etc). A tag is used to 61 /// specify which representation is used in the following YAML document. 62 /// To work, there must be a YamlIOTaggedDocumentHandler registered that 63 /// handles each tag type. 64 class YamlIOTaggedDocumentHandler { 65 public: 66 virtual ~YamlIOTaggedDocumentHandler(); 67 68 /// This method is called on each registered YamlIOTaggedDocumentHandler 69 /// until one returns true. If the subclass handles tag type !xyz, then 70 /// this method should call io.mapTag("!xzy") to see if that is the current 71 /// document type, and if so, process the rest of the document using 72 /// YAML I/O, then convert the result into an lld::File* and return it. 73 virtual bool handledDocTag(llvm::yaml::IO &io, const lld::File *&f) const = 0; 74 }; 75 76 /// A registry to hold the list of currently registered Readers and 77 /// tables which map Reference kind values to strings. 78 /// The linker does not directly invoke Readers. Instead, it registers 79 /// Readers based on it configuration and command line options, then calls 80 /// the Registry object to parse files. 81 class Registry { 82 public: 83 Registry(); 84 85 /// Walk the list of registered Readers and find one that can parse the 86 /// supplied file and parse it. 87 ErrorOr<std::unique_ptr<File>> 88 loadFile(std::unique_ptr<MemoryBuffer> mb) const; 89 90 /// Walk the list of registered kind tables to convert a Reference Kind 91 /// name to a value. 92 bool referenceKindFromString(StringRef inputStr, Reference::KindNamespace &ns, 93 Reference::KindArch &a, 94 Reference::KindValue &value) const; 95 96 /// Walk the list of registered kind tables to convert a Reference Kind 97 /// value to a string. 98 bool referenceKindToString(Reference::KindNamespace ns, Reference::KindArch a, 99 Reference::KindValue value, StringRef &) const; 100 101 /// Walk the list of registered tag handlers and have the one that handles 102 /// the current document type process the yaml into an lld::File*. 103 bool handleTaggedDoc(llvm::yaml::IO &io, const lld::File *&file) const; 104 105 // These methods are called to dynamically add support for various file 106 // formats. The methods are also implemented in the appropriate lib*.a 107 // library, so that the code for handling a format is only linked in, if this 108 // method is used. Any options that a Reader might need must be passed 109 // as parameters to the addSupport*() method. 110 void addSupportArchives(bool logLoading); 111 void addSupportYamlFiles(); 112 void addSupportMachOObjects(MachOLinkingContext &); 113 114 /// To convert between kind values and names, the registry walks the list 115 /// of registered kind tables. Each table is a zero terminated array of 116 /// KindStrings elements. 117 struct KindStrings { 118 Reference::KindValue value; 119 StringRef name; 120 }; 121 122 /// A Reference Kind value is a tuple of <namespace, arch, value>. All 123 /// entries in a conversion table have the same <namespace, arch>. The 124 /// array then contains the value/name pairs. 125 void addKindTable(Reference::KindNamespace ns, Reference::KindArch arch, 126 const KindStrings array[]); 127 128 private: 129 struct KindEntry { 130 Reference::KindNamespace ns; 131 Reference::KindArch arch; 132 const KindStrings *array; 133 }; 134 135 void add(std::unique_ptr<Reader>); 136 void add(std::unique_ptr<YamlIOTaggedDocumentHandler>); 137 138 std::vector<std::unique_ptr<Reader>> _readers; 139 std::vector<std::unique_ptr<YamlIOTaggedDocumentHandler>> _yamlHandlers; 140 std::vector<KindEntry> _kindEntries; 141 }; 142 143 // Utilities for building a KindString table. For instance: 144 // static const Registry::KindStrings table[] = { 145 // LLD_KIND_STRING_ENTRY(R_VAX_ADDR16), 146 // LLD_KIND_STRING_ENTRY(R_VAX_DATA16), 147 // LLD_KIND_STRING_END 148 // }; 149 #define LLD_KIND_STRING_ENTRY(name) { name, #name } 150 #define LLD_KIND_STRING_END { 0, "" } 151 152 } // end namespace lld 153 154 #endif // LLD_CORE_READER_H 155