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/ADT/iterator_range.h" 19 #include "llvm/Object/Binary.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/ErrorOr.h" 22 #include "llvm/Support/FileSystem.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 25 namespace llvm { 26 namespace object { 27 struct ArchiveMemberHeader { 28 char Name[16]; 29 char LastModified[12]; 30 char UID[6]; 31 char GID[6]; 32 char AccessMode[8]; 33 char Size[10]; ///< Size of data, not including header or padding. 34 char Terminator[2]; 35 36 /// Get the name without looking up long names. 37 llvm::StringRef getName() const; 38 39 /// Members are not larger than 4GB. 40 uint32_t getSize() const; 41 42 sys::fs::perms getAccessMode() const; 43 sys::TimeValue getLastModified() const; 44 unsigned getUID() const; 45 unsigned getGID() const; 46 }; 47 48 class Archive : public Binary { 49 virtual void anchor(); 50 public: 51 class Child { 52 const Archive *Parent; 53 /// \brief Includes header but not padding byte. 54 StringRef Data; 55 /// \brief Offset from Data to the start of the file. 56 uint16_t StartOfFile; 57 getHeader()58 const ArchiveMemberHeader *getHeader() const { 59 return reinterpret_cast<const ArchiveMemberHeader *>(Data.data()); 60 } 61 62 public: 63 Child(const Archive *Parent, const char *Start); 64 65 bool operator ==(const Child &other) const { 66 assert(Parent == other.Parent); 67 return Data.begin() == other.Data.begin(); 68 } 69 70 bool operator <(const Child &other) const { 71 return Data.begin() < other.Data.begin(); 72 } 73 74 Child getNext() const; 75 76 ErrorOr<StringRef> getName() const; getRawName()77 StringRef getRawName() const { return getHeader()->getName(); } getLastModified()78 sys::TimeValue getLastModified() const { 79 return getHeader()->getLastModified(); 80 } getUID()81 unsigned getUID() const { return getHeader()->getUID(); } getGID()82 unsigned getGID() const { return getHeader()->getGID(); } getAccessMode()83 sys::fs::perms getAccessMode() const { 84 return getHeader()->getAccessMode(); 85 } 86 /// \return the size of the archive member without the header or padding. 87 uint64_t getSize() const; 88 getBuffer()89 StringRef getBuffer() const { 90 return StringRef(Data.data() + StartOfFile, getSize()); 91 } 92 93 ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; 94 95 ErrorOr<std::unique_ptr<Binary>> 96 getAsBinary(LLVMContext *Context = nullptr) const; 97 }; 98 99 class child_iterator { 100 Child child; 101 102 public: child_iterator()103 child_iterator() : child(Child(nullptr, nullptr)) {} child_iterator(const Child & c)104 child_iterator(const Child &c) : child(c) {} 105 const Child *operator->() const { return &child; } 106 const Child &operator*() const { return child; } 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 Symbol(const Archive * p,uint32_t symi,uint32_t stri)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: symbol_iterator(const Symbol & s)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(MemoryBufferRef Source, std::error_code &EC); 168 static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source); 169 170 enum Kind { 171 K_GNU, 172 K_BSD, 173 K_COFF 174 }; 175 kind()176 Kind kind() const { return (Kind)Format; } 177 178 child_iterator child_begin(bool SkipInternal = true) const; 179 child_iterator child_end() const; 180 iterator_range<child_iterator> children(bool SkipInternal = true) const { 181 return iterator_range<child_iterator>(child_begin(SkipInternal), 182 child_end()); 183 } 184 185 symbol_iterator symbol_begin() const; 186 symbol_iterator symbol_end() const; 187 188 // Cast methods. classof(Binary const * v)189 static inline bool classof(Binary const *v) { 190 return v->isArchive(); 191 } 192 193 // check if a symbol is in the archive 194 child_iterator findSym(StringRef name) const; 195 196 bool hasSymbolTable() const; 197 198 private: 199 child_iterator SymbolTable; 200 child_iterator StringTable; 201 child_iterator FirstRegular; 202 unsigned Format : 2; 203 unsigned IsThin : 1; 204 }; 205 206 } 207 } 208 209 #endif 210