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