LLVM API Documentation

Archive.h
Go to the documentation of this file.
00001 //===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file declares the ar archive file format class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_OBJECT_ARCHIVE_H
00015 #define LLVM_OBJECT_ARCHIVE_H
00016 
00017 #include "llvm/ADT/StringRef.h"
00018 #include "llvm/Object/Binary.h"
00019 #include "llvm/Support/ErrorHandling.h"
00020 #include "llvm/Support/ErrorOr.h"
00021 #include "llvm/Support/FileSystem.h"
00022 #include "llvm/Support/MemoryBuffer.h"
00023 
00024 namespace llvm {
00025 namespace object {
00026 struct ArchiveMemberHeader {
00027   char Name[16];
00028   char LastModified[12];
00029   char UID[6];
00030   char GID[6];
00031   char AccessMode[8];
00032   char Size[10]; ///< Size of data, not including header or padding.
00033   char Terminator[2];
00034 
00035   /// Get the name without looking up long names.
00036   llvm::StringRef getName() const;
00037 
00038   /// Members are not larger than 4GB.
00039   uint32_t getSize() const;
00040 
00041   sys::fs::perms getAccessMode() const;
00042   sys::TimeValue getLastModified() const;
00043   unsigned getUID() const;
00044   unsigned getGID() const;
00045 };
00046 
00047 class Archive : public Binary {
00048   virtual void anchor();
00049 public:
00050   class Child {
00051     const Archive *Parent;
00052     /// \brief Includes header but not padding byte.
00053     StringRef Data;
00054     /// \brief Offset from Data to the start of the file.
00055     uint16_t StartOfFile;
00056 
00057     const ArchiveMemberHeader *getHeader() const {
00058       return reinterpret_cast<const ArchiveMemberHeader *>(Data.data());
00059     }
00060 
00061   public:
00062     Child(const Archive *Parent, const char *Start);
00063 
00064     bool operator ==(const Child &other) const {
00065       assert(Parent == other.Parent);
00066       return Data.begin() == other.Data.begin();
00067     }
00068 
00069     bool operator <(const Child &other) const {
00070       return Data.begin() < other.Data.begin();
00071     }
00072 
00073     Child getNext() const;
00074 
00075     ErrorOr<StringRef> getName() const;
00076     StringRef getRawName() const { return getHeader()->getName(); }
00077     sys::TimeValue getLastModified() const {
00078       return getHeader()->getLastModified();
00079     }
00080     unsigned getUID() const { return getHeader()->getUID(); }
00081     unsigned getGID() const { return getHeader()->getGID(); }
00082     sys::fs::perms getAccessMode() const {
00083       return getHeader()->getAccessMode();
00084     }
00085     /// \return the size of the archive member without the header or padding.
00086     uint64_t getSize() const { return Data.size() - StartOfFile; }
00087 
00088     StringRef getBuffer() const {
00089       return StringRef(Data.data() + StartOfFile, getSize());
00090     }
00091 
00092     ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
00093 
00094     ErrorOr<std::unique_ptr<Binary>>
00095     getAsBinary(LLVMContext *Context = nullptr) const;
00096   };
00097 
00098   class child_iterator {
00099     Child child;
00100   public:
00101     child_iterator() : child(Child(nullptr, nullptr)) {}
00102     child_iterator(const Child &c) : child(c) {}
00103     const Child* operator->() const {
00104       return &child;
00105     }
00106 
00107     bool operator==(const child_iterator &other) const {
00108       return child == other.child;
00109     }
00110 
00111     bool operator!=(const child_iterator &other) const {
00112       return !(*this == other);
00113     }
00114 
00115     bool operator <(const child_iterator &other) const {
00116       return child < other.child;
00117     }
00118 
00119     child_iterator& operator++() {  // Preincrement
00120       child = child.getNext();
00121       return *this;
00122     }
00123   };
00124 
00125   class Symbol {
00126     const Archive *Parent;
00127     uint32_t SymbolIndex;
00128     uint32_t StringIndex; // Extra index to the string.
00129 
00130   public:
00131     bool operator ==(const Symbol &other) const {
00132       return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
00133     }
00134 
00135     Symbol(const Archive *p, uint32_t symi, uint32_t stri)
00136       : Parent(p)
00137       , SymbolIndex(symi)
00138       , StringIndex(stri) {}
00139     StringRef getName() const;
00140     ErrorOr<child_iterator> getMember() const;
00141     Symbol getNext() const;
00142   };
00143 
00144   class symbol_iterator {
00145     Symbol symbol;
00146   public:
00147     symbol_iterator(const Symbol &s) : symbol(s) {}
00148     const Symbol *operator->() const {
00149       return &symbol;
00150     }
00151 
00152     bool operator==(const symbol_iterator &other) const {
00153       return symbol == other.symbol;
00154     }
00155 
00156     bool operator!=(const symbol_iterator &other) const {
00157       return !(*this == other);
00158     }
00159 
00160     symbol_iterator& operator++() {  // Preincrement
00161       symbol = symbol.getNext();
00162       return *this;
00163     }
00164   };
00165 
00166   Archive(MemoryBufferRef Source, std::error_code &EC);
00167   static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
00168 
00169   enum Kind {
00170     K_GNU,
00171     K_BSD,
00172     K_COFF
00173   };
00174 
00175   Kind kind() const { 
00176     return Format;
00177   }
00178 
00179   child_iterator child_begin(bool SkipInternal = true) const;
00180   child_iterator child_end() const;
00181 
00182   symbol_iterator symbol_begin() const;
00183   symbol_iterator symbol_end() const;
00184 
00185   // Cast methods.
00186   static inline bool classof(Binary const *v) {
00187     return v->isArchive();
00188   }
00189 
00190   // check if a symbol is in the archive
00191   child_iterator findSym(StringRef name) const;
00192 
00193   bool hasSymbolTable() const;
00194 
00195 private:
00196   child_iterator SymbolTable;
00197   child_iterator StringTable;
00198   child_iterator FirstRegular;
00199   Kind Format;
00200 };
00201 
00202 }
00203 }
00204 
00205 #endif