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