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; getRawLastModifiedArchiveMemberHeader44 llvm::StringRef getRawLastModified() const { 45 return StringRef(LastModified, sizeof(LastModified)).rtrim(" "); 46 } 47 unsigned getUID() const; 48 unsigned getGID() const; 49 }; 50 51 class Archive : public Binary { 52 virtual void anchor(); 53 public: 54 class Child { 55 const Archive *Parent; 56 /// \brief Includes header but not padding byte. 57 StringRef Data; 58 /// \brief Offset from Data to the start of the file. 59 uint16_t StartOfFile; 60 getHeader()61 const ArchiveMemberHeader *getHeader() const { 62 return reinterpret_cast<const ArchiveMemberHeader *>(Data.data()); 63 } 64 65 public: 66 Child(const Archive *Parent, const char *Start); 67 68 bool operator ==(const Child &other) const { 69 assert(Parent == other.Parent); 70 return Data.begin() == other.Data.begin(); 71 } 72 73 bool operator <(const Child &other) const { 74 return Data.begin() < other.Data.begin(); 75 } 76 77 Child getNext() const; 78 79 ErrorOr<StringRef> getName() const; getRawName()80 StringRef getRawName() const { return getHeader()->getName(); } getLastModified()81 sys::TimeValue getLastModified() const { 82 return getHeader()->getLastModified(); 83 } getRawLastModified()84 StringRef getRawLastModified() const { 85 return getHeader()->getRawLastModified(); 86 } getUID()87 unsigned getUID() const { return getHeader()->getUID(); } getGID()88 unsigned getGID() const { return getHeader()->getGID(); } getAccessMode()89 sys::fs::perms getAccessMode() const { 90 return getHeader()->getAccessMode(); 91 } 92 /// \return the size of the archive member without the header or padding. 93 uint64_t getSize() const; 94 /// \return the size in the archive header for this member. 95 uint64_t getRawSize() const; 96 getBuffer()97 StringRef getBuffer() const { 98 return StringRef(Data.data() + StartOfFile, getSize()); 99 } 100 uint64_t getChildOffset() const; 101 102 ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; 103 104 ErrorOr<std::unique_ptr<Binary>> 105 getAsBinary(LLVMContext *Context = nullptr) const; 106 }; 107 108 class child_iterator { 109 Child child; 110 111 public: child_iterator()112 child_iterator() : child(Child(nullptr, nullptr)) {} child_iterator(const Child & c)113 child_iterator(const Child &c) : child(c) {} 114 const Child *operator->() const { return &child; } 115 const Child &operator*() const { return child; } 116 117 bool operator==(const child_iterator &other) const { 118 return child == other.child; 119 } 120 121 bool operator!=(const child_iterator &other) const { 122 return !(*this == other); 123 } 124 125 bool operator<(const child_iterator &other) const { 126 return child < other.child; 127 } 128 129 child_iterator &operator++() { // Preincrement 130 child = child.getNext(); 131 return *this; 132 } 133 }; 134 135 class Symbol { 136 const Archive *Parent; 137 uint32_t SymbolIndex; 138 uint32_t StringIndex; // Extra index to the string. 139 140 public: 141 bool operator ==(const Symbol &other) const { 142 return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); 143 } 144 Symbol(const Archive * p,uint32_t symi,uint32_t stri)145 Symbol(const Archive *p, uint32_t symi, uint32_t stri) 146 : Parent(p) 147 , SymbolIndex(symi) 148 , StringIndex(stri) {} 149 StringRef getName() const; 150 ErrorOr<child_iterator> getMember() const; 151 Symbol getNext() const; 152 }; 153 154 class symbol_iterator { 155 Symbol symbol; 156 public: symbol_iterator(const Symbol & s)157 symbol_iterator(const Symbol &s) : symbol(s) {} 158 const Symbol *operator->() const { return &symbol; } 159 const Symbol &operator*() const { return symbol; } 160 161 bool operator==(const symbol_iterator &other) const { 162 return symbol == other.symbol; 163 } 164 165 bool operator!=(const symbol_iterator &other) const { 166 return !(*this == other); 167 } 168 169 symbol_iterator& operator++() { // Preincrement 170 symbol = symbol.getNext(); 171 return *this; 172 } 173 }; 174 175 Archive(MemoryBufferRef Source, std::error_code &EC); 176 static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source); 177 178 enum Kind { 179 K_GNU, 180 K_MIPS64, 181 K_BSD, 182 K_COFF 183 }; 184 kind()185 Kind kind() const { return (Kind)Format; } 186 187 child_iterator child_begin(bool SkipInternal = true) const; 188 child_iterator child_end() const; 189 iterator_range<child_iterator> children(bool SkipInternal = true) const { 190 return iterator_range<child_iterator>(child_begin(SkipInternal), 191 child_end()); 192 } 193 194 symbol_iterator symbol_begin() const; 195 symbol_iterator symbol_end() const; symbols()196 iterator_range<symbol_iterator> symbols() const { 197 return iterator_range<symbol_iterator>(symbol_begin(), symbol_end()); 198 } 199 200 // Cast methods. classof(Binary const * v)201 static inline bool classof(Binary const *v) { 202 return v->isArchive(); 203 } 204 205 // check if a symbol is in the archive 206 child_iterator findSym(StringRef name) const; 207 208 bool hasSymbolTable() const; getSymbolTableChild()209 child_iterator getSymbolTableChild() const { return SymbolTable; } 210 211 private: 212 child_iterator SymbolTable; 213 child_iterator StringTable; 214 child_iterator FirstRegular; 215 unsigned Format : 2; 216 unsigned IsThin : 1; 217 }; 218 219 } 220 } 221 222 #endif 223