Home | History | Annotate | Download | only in Object
      1 //===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file declares the ar archive file format class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_OBJECT_ARCHIVE_H
     15 #define LLVM_OBJECT_ARCHIVE_H
     16 
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/Object/Binary.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/ErrorOr.h"
     21 #include "llvm/Support/FileSystem.h"
     22 #include "llvm/Support/MemoryBuffer.h"
     23 
     24 namespace llvm {
     25 namespace object {
     26 struct ArchiveMemberHeader {
     27   char Name[16];
     28   char LastModified[12];
     29   char UID[6];
     30   char GID[6];
     31   char AccessMode[8];
     32   char Size[10]; ///< Size of data, not including header or padding.
     33   char Terminator[2];
     34 
     35   /// Get the name without looking up long names.
     36   llvm::StringRef getName() const;
     37 
     38   /// Members are not larger than 4GB.
     39   uint32_t getSize() const;
     40 
     41   sys::fs::perms getAccessMode() const;
     42   sys::TimeValue getLastModified() const;
     43   unsigned getUID() const;
     44   unsigned getGID() const;
     45 };
     46 
     47 class Archive : public Binary {
     48   virtual void anchor();
     49 public:
     50   class Child {
     51     const Archive *Parent;
     52     /// \brief Includes header but not padding byte.
     53     StringRef Data;
     54     /// \brief Offset from Data to the start of the file.
     55     uint16_t StartOfFile;
     56 
     57     const ArchiveMemberHeader *getHeader() const {
     58       return reinterpret_cast<const ArchiveMemberHeader *>(Data.data());
     59     }
     60 
     61   public:
     62     Child(const Archive *Parent, const char *Start);
     63 
     64     bool operator ==(const Child &other) const {
     65       assert(Parent == other.Parent);
     66       return Data.begin() == other.Data.begin();
     67     }
     68 
     69     bool operator <(const Child &other) const {
     70       return Data.begin() < other.Data.begin();
     71     }
     72 
     73     Child getNext() const;
     74 
     75     ErrorOr<StringRef> getName() const;
     76     StringRef getRawName() const { return getHeader()->getName(); }
     77     sys::TimeValue getLastModified() const {
     78       return getHeader()->getLastModified();
     79     }
     80     unsigned getUID() const { return getHeader()->getUID(); }
     81     unsigned getGID() const { return getHeader()->getGID(); }
     82     sys::fs::perms getAccessMode() const {
     83       return getHeader()->getAccessMode();
     84     }
     85     /// \return the size of the archive member without the header or padding.
     86     uint64_t getSize() const { return Data.size() - StartOfFile; }
     87 
     88     StringRef getBuffer() const {
     89       return StringRef(Data.data() + StartOfFile, getSize());
     90     }
     91 
     92     ErrorOr<std::unique_ptr<MemoryBuffer>>
     93     getMemoryBuffer(bool FullPath = false) const;
     94 
     95     ErrorOr<std::unique_ptr<Binary>>
     96     getAsBinary(LLVMContext *Context = nullptr) const;
     97   };
     98 
     99   class child_iterator {
    100     Child child;
    101   public:
    102     child_iterator() : child(Child(nullptr, nullptr)) {}
    103     child_iterator(const Child &c) : child(c) {}
    104     const Child* operator->() const {
    105       return &child;
    106     }
    107 
    108     bool operator==(const child_iterator &other) const {
    109       return child == other.child;
    110     }
    111 
    112     bool operator!=(const child_iterator &other) const {
    113       return !(*this == other);
    114     }
    115 
    116     bool operator <(const child_iterator &other) const {
    117       return child < other.child;
    118     }
    119 
    120     child_iterator& operator++() {  // Preincrement
    121       child = child.getNext();
    122       return *this;
    123     }
    124   };
    125 
    126   class Symbol {
    127     const Archive *Parent;
    128     uint32_t SymbolIndex;
    129     uint32_t StringIndex; // Extra index to the string.
    130 
    131   public:
    132     bool operator ==(const Symbol &other) const {
    133       return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
    134     }
    135 
    136     Symbol(const Archive *p, uint32_t symi, uint32_t stri)
    137       : Parent(p)
    138       , SymbolIndex(symi)
    139       , StringIndex(stri) {}
    140     StringRef getName() const;
    141     ErrorOr<child_iterator> getMember() const;
    142     Symbol getNext() const;
    143   };
    144 
    145   class symbol_iterator {
    146     Symbol symbol;
    147   public:
    148     symbol_iterator(const Symbol &s) : symbol(s) {}
    149     const Symbol *operator->() const {
    150       return &symbol;
    151     }
    152 
    153     bool operator==(const symbol_iterator &other) const {
    154       return symbol == other.symbol;
    155     }
    156 
    157     bool operator!=(const symbol_iterator &other) const {
    158       return !(*this == other);
    159     }
    160 
    161     symbol_iterator& operator++() {  // Preincrement
    162       symbol = symbol.getNext();
    163       return *this;
    164     }
    165   };
    166 
    167   Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &EC);
    168   static ErrorOr<Archive *> create(std::unique_ptr<MemoryBuffer> Source);
    169 
    170   enum Kind {
    171     K_GNU,
    172     K_BSD,
    173     K_COFF
    174   };
    175 
    176   Kind kind() const {
    177     return Format;
    178   }
    179 
    180   child_iterator child_begin(bool SkipInternal = true) const;
    181   child_iterator child_end() const;
    182 
    183   symbol_iterator symbol_begin() const;
    184   symbol_iterator symbol_end() const;
    185 
    186   // Cast methods.
    187   static inline bool classof(Binary const *v) {
    188     return v->isArchive();
    189   }
    190 
    191   // check if a symbol is in the archive
    192   child_iterator findSym(StringRef name) const;
    193 
    194   bool hasSymbolTable() const;
    195 
    196 private:
    197   child_iterator SymbolTable;
    198   child_iterator StringTable;
    199   child_iterator FirstRegular;
    200   Kind Format;
    201 };
    202 
    203 }
    204 }
    205 
    206 #endif
    207