LCOV - code coverage report
Current view: top level - include/llvm/Object - Archive.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 29 36 80.6 %
Date: 2018-10-20 13:21:21 Functions: 3 9 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/Optional.h"
      18             : #include "llvm/ADT/StringRef.h"
      19             : #include "llvm/ADT/iterator_range.h"
      20             : #include "llvm/Object/Binary.h"
      21             : #include "llvm/Support/Chrono.h"
      22             : #include "llvm/Support/Error.h"
      23             : #include "llvm/Support/FileSystem.h"
      24             : #include "llvm/Support/MemoryBuffer.h"
      25             : #include <algorithm>
      26             : #include <cassert>
      27             : #include <cstdint>
      28             : #include <memory>
      29             : #include <string>
      30             : #include <vector>
      31             : 
      32             : namespace llvm {
      33             : namespace object {
      34             : 
      35             : class Archive;
      36             : 
      37             : class ArchiveMemberHeader {
      38             : public:
      39             :   friend class Archive;
      40             : 
      41             :   ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
      42             :                       uint64_t Size, Error *Err);
      43             :   // ArchiveMemberHeader() = default;
      44             : 
      45             :   /// Get the name without looking up long names.
      46             :   Expected<StringRef> getRawName() const;
      47             : 
      48             :   /// Get the name looking up long names.
      49             :   Expected<StringRef> getName(uint64_t Size) const;
      50             : 
      51             :   /// Members are not larger than 4GB.
      52             :   Expected<uint32_t> getSize() const;
      53             : 
      54             :   Expected<sys::fs::perms> getAccessMode() const;
      55             :   Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
      56             : 
      57           0 :   StringRef getRawLastModified() const {
      58          37 :     return StringRef(ArMemHdr->LastModified,
      59          37 :                      sizeof(ArMemHdr->LastModified)).rtrim(' ');
      60             :   }
      61             : 
      62             :   Expected<unsigned> getUID() const;
      63             :   Expected<unsigned> getGID() const;
      64             : 
      65             :   // This returns the size of the private struct ArMemHdrType
      66           0 :   uint64_t getSizeOf() const {
      67           0 :     return sizeof(ArMemHdrType);
      68             :   }
      69             : 
      70             : private:
      71             :   struct ArMemHdrType {
      72             :     char Name[16];
      73             :     char LastModified[12];
      74             :     char UID[6];
      75             :     char GID[6];
      76             :     char AccessMode[8];
      77             :     char Size[10]; ///< Size of data, not including header or padding.
      78             :     char Terminator[2];
      79             :   };
      80             :   Archive const *Parent;
      81             :   ArMemHdrType const *ArMemHdr;
      82             : };
      83             : 
      84         110 : class Archive : public Binary {
      85             :   virtual void anchor();
      86             : 
      87             : public:
      88             :   class Child {
      89             :     friend Archive;
      90             :     friend ArchiveMemberHeader;
      91             : 
      92             :     const Archive *Parent;
      93             :     ArchiveMemberHeader Header;
      94             :     /// Includes header but not padding byte.
      95             :     StringRef Data;
      96             :     /// Offset from Data to the start of the file.
      97             :     uint16_t StartOfFile;
      98             : 
      99             :     Expected<bool> isThinMember() const;
     100             : 
     101             :   public:
     102             :     Child(const Archive *Parent, const char *Start, Error *Err);
     103             :     Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);
     104             : 
     105             :     bool operator ==(const Child &other) const {
     106             :       assert(!Parent || !other.Parent || Parent == other.Parent);
     107        2239 :       return Data.begin() == other.Data.begin();
     108             :     }
     109             : 
     110           0 :     const Archive *getParent() const { return Parent; }
     111             :     Expected<Child> getNext() const;
     112             : 
     113             :     Expected<StringRef> getName() const;
     114             :     Expected<std::string> getFullName() const;
     115        3283 :     Expected<StringRef> getRawName() const { return Header.getRawName(); }
     116             : 
     117             :     Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const {
     118         100 :       return Header.getLastModified();
     119             :     }
     120             : 
     121             :     StringRef getRawLastModified() const {
     122          37 :       return Header.getRawLastModified();
     123             :     }
     124             : 
     125          68 :     Expected<unsigned> getUID() const { return Header.getUID(); }
     126          67 :     Expected<unsigned> getGID() const { return Header.getGID(); }
     127             : 
     128             :     Expected<sys::fs::perms> getAccessMode() const {
     129          77 :       return Header.getAccessMode();
     130             :     }
     131             : 
     132             :     /// \return the size of the archive member without the header or padding.
     133             :     Expected<uint64_t> getSize() const;
     134             :     /// \return the size in the archive header for this member.
     135             :     Expected<uint64_t> getRawSize() const;
     136             : 
     137             :     Expected<StringRef> getBuffer() const;
     138             :     uint64_t getChildOffset() const;
     139             : 
     140             :     Expected<MemoryBufferRef> getMemoryBufferRef() const;
     141             : 
     142             :     Expected<std::unique_ptr<Binary>>
     143             :     getAsBinary(LLVMContext *Context = nullptr) const;
     144             :   };
     145             : 
     146             :   class child_iterator {
     147             :     Child C;
     148             :     Error *E = nullptr;
     149             : 
     150             :   public:
     151             :     child_iterator() : C(Child(nullptr, nullptr, nullptr)) {}
     152         924 :     child_iterator(const Child &C, Error *E) : C(C), E(E) {}
     153             : 
     154             :     const Child *operator->() const { return &C; }
     155             :     const Child &operator*() const { return C; }
     156             : 
     157             :     bool operator==(const child_iterator &other) const {
     158             :       // Ignore errors here: If an error occurred during increment then getNext
     159             :       // will have been set to child_end(), and the following comparison should
     160             :       // do the right thing.
     161             :       return C == other.C;
     162             :     }
     163             : 
     164             :     bool operator!=(const child_iterator &other) const {
     165             :       return !(*this == other);
     166             :     }
     167             : 
     168             :     // Code in loops with child_iterators must check for errors on each loop
     169             :     // iteration.  And if there is an error break out of the loop.
     170        1724 :     child_iterator &operator++() { // Preincrement
     171             :       assert(E && "Can't increment iterator with no Error attached");
     172        1724 :       ErrorAsOutParameter ErrAsOutParam(E);
     173        1724 :       if (auto ChildOrErr = C.getNext())
     174        1720 :         C = *ChildOrErr;
     175             :       else {
     176           4 :         C = C.getParent()->child_end().C;
     177           4 :         *E = ChildOrErr.takeError();
     178           4 :         E = nullptr;
     179             :       }
     180        1724 :       return *this;
     181             :     }
     182             :   };
     183             : 
     184             :   class Symbol {
     185             :     const Archive *Parent;
     186             :     uint32_t SymbolIndex;
     187             :     uint32_t StringIndex; // Extra index to the string.
     188             : 
     189             :   public:
     190             :     Symbol(const Archive *p, uint32_t symi, uint32_t stri)
     191             :       : Parent(p)
     192             :       , SymbolIndex(symi)
     193             :       , StringIndex(stri) {}
     194             : 
     195           0 :     bool operator ==(const Symbol &other) const {
     196        1071 :       return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
     197             :     }
     198             : 
     199             :     StringRef getName() const;
     200             :     Expected<Child> getMember() const;
     201             :     Symbol getNext() const;
     202             :   };
     203             : 
     204             :   class symbol_iterator {
     205             :     Symbol symbol;
     206             : 
     207             :   public:
     208             :     symbol_iterator(const Symbol &s) : symbol(s) {}
     209             : 
     210             :     const Symbol *operator->() const { return &symbol; }
     211             :     const Symbol &operator*() const { return symbol; }
     212             : 
     213             :     bool operator==(const symbol_iterator &other) const {
     214        1071 :       return symbol == other.symbol;
     215             :     }
     216             : 
     217             :     bool operator!=(const symbol_iterator &other) const {
     218             :       return !(*this == other);
     219             :     }
     220             : 
     221             :     symbol_iterator& operator++() {  // Preincrement
     222         807 :       symbol = symbol.getNext();
     223             :       return *this;
     224             :     }
     225             :   };
     226             : 
     227             :   Archive(MemoryBufferRef Source, Error &Err);
     228             :   static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
     229             : 
     230             :   enum Kind {
     231             :     K_GNU,
     232             :     K_GNU64,
     233             :     K_BSD,
     234             :     K_DARWIN,
     235             :     K_DARWIN64,
     236             :     K_COFF
     237             :   };
     238             : 
     239       11214 :   Kind kind() const { return (Kind)Format; }
     240         525 :   bool isThin() const { return IsThin; }
     241             : 
     242             :   child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
     243             :   child_iterator child_end() const;
     244         367 :   iterator_range<child_iterator> children(Error &Err,
     245             :                                           bool SkipInternal = true) const {
     246         367 :     return make_range(child_begin(Err, SkipInternal), child_end());
     247             :   }
     248             : 
     249             :   symbol_iterator symbol_begin() const;
     250             :   symbol_iterator symbol_end() const;
     251         206 :   iterator_range<symbol_iterator> symbols() const {
     252         206 :     return make_range(symbol_begin(), symbol_end());
     253             :   }
     254             : 
     255             :   // Cast methods.
     256             :   static bool classof(Binary const *v) {
     257        6056 :     return v->isArchive();
     258             :   }
     259             : 
     260             :   // check if a symbol is in the archive
     261             :   Expected<Optional<Child>> findSym(StringRef name) const;
     262             : 
     263             :   bool isEmpty() const;
     264             :   bool hasSymbolTable() const;
     265           0 :   StringRef getSymbolTable() const { return SymbolTable; }
     266           0 :   StringRef getStringTable() const { return StringTable; }
     267             :   uint32_t getNumberOfSymbols() const;
     268             : 
     269             :   std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
     270             :     return std::move(ThinBuffers);
     271             :   }
     272             : 
     273             : private:
     274             :   StringRef SymbolTable;
     275             :   StringRef StringTable;
     276             : 
     277             :   StringRef FirstRegularData;
     278             :   uint16_t FirstRegularStartOfFile = -1;
     279             :   void setFirstRegular(const Child &C);
     280             : 
     281             :   unsigned Format : 3;
     282             :   unsigned IsThin : 1;
     283             :   mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
     284             : };
     285             : 
     286             : } // end namespace object
     287             : } // end namespace llvm
     288             : 
     289             : #endif // LLVM_OBJECT_ARCHIVE_H

Generated by: LCOV version 1.13