• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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