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