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