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
22namespace llvm {
23namespace yaml {
24class IO;
25} // end namespace yaml
26} // end namespace llvm
27
28namespace lld {
29
30class File;
31class LinkingContext;
32class 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.
38class Reader {
39public:
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.
64class YamlIOTaggedDocumentHandler {
65public:
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.
81class Registry {
82public:
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
128private:
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