1 //===- Archive.h - ar archive file format -----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the ar archive file format class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_OBJECT_ARCHIVE_H 14 #define LLVM_OBJECT_ARCHIVE_H 15 16 #include "llvm/ADT/Optional.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/fallible_iterator.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 Expected<uint64_t> getSize() const; 52 53 Expected<sys::fs::perms> getAccessMode() const; 54 Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const; 55 56 StringRef getRawLastModified() const { 57 return StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified)) 58 .rtrim(' '); 59 } 60 61 Expected<unsigned> getUID() const; 62 Expected<unsigned> getGID() const; 63 64 // This returns the size of the private struct ArMemHdrType 65 uint64_t getSizeOf() const { return sizeof(ArMemHdrType); } 66 67 private: 68 struct ArMemHdrType { 69 char Name[16]; 70 char LastModified[12]; 71 char UID[6]; 72 char GID[6]; 73 char AccessMode[8]; 74 char Size[10]; ///< Size of data, not including header or padding. 75 char Terminator[2]; 76 }; 77 Archive const *Parent; 78 ArMemHdrType const *ArMemHdr; 79 }; 80 81 class Archive : public Binary { 82 virtual void anchor(); 83 84 public: 85 class Child { 86 friend Archive; 87 friend ArchiveMemberHeader; 88 89 const Archive *Parent; 90 ArchiveMemberHeader Header; 91 /// Includes header but not padding byte. 92 StringRef Data; 93 /// Offset from Data to the start of the file. 94 uint16_t StartOfFile; 95 96 Expected<bool> isThinMember() const; 97 98 public: 99 Child(const Archive *Parent, const char *Start, Error *Err); 100 Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); 101 102 bool operator==(const Child &other) const { 103 assert(!Parent || !other.Parent || Parent == other.Parent); 104 return Data.begin() == other.Data.begin(); 105 } 106 107 const Archive *getParent() const { return Parent; } 108 Expected<Child> getNext() const; 109 110 Expected<StringRef> getName() const; 111 Expected<std::string> getFullName() const; 112 Expected<StringRef> getRawName() const { return Header.getRawName(); } 113 114 Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const { 115 return Header.getLastModified(); 116 } 117 118 StringRef getRawLastModified() const { return Header.getRawLastModified(); } 119 120 Expected<unsigned> getUID() const { return Header.getUID(); } 121 Expected<unsigned> getGID() const { return Header.getGID(); } 122 123 Expected<sys::fs::perms> getAccessMode() const { 124 return Header.getAccessMode(); 125 } 126 127 /// \return the size of the archive member without the header or padding. 128 Expected<uint64_t> getSize() const; 129 /// \return the size in the archive header for this member. 130 Expected<uint64_t> getRawSize() const; 131 132 Expected<StringRef> getBuffer() const; 133 uint64_t getChildOffset() const; 134 uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; } 135 136 Expected<MemoryBufferRef> getMemoryBufferRef() const; 137 138 Expected<std::unique_ptr<Binary>> 139 getAsBinary(LLVMContext *Context = nullptr) const; 140 }; 141 142 class ChildFallibleIterator { 143 Child C; 144 145 public: 146 ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {} 147 ChildFallibleIterator(const Child &C) : C(C) {} 148 149 const Child *operator->() const { return &C; } 150 const Child &operator*() const { return C; } 151 152 bool operator==(const ChildFallibleIterator &other) const { 153 // Ignore errors here: If an error occurred during increment then getNext 154 // will have been set to child_end(), and the following comparison should 155 // do the right thing. 156 return C == other.C; 157 } 158 159 bool operator!=(const ChildFallibleIterator &other) const { 160 return !(*this == other); 161 } 162 163 Error inc() { 164 auto NextChild = C.getNext(); 165 if (!NextChild) 166 return NextChild.takeError(); 167 C = std::move(*NextChild); 168 return Error::success(); 169 } 170 }; 171 172 using child_iterator = fallible_iterator<ChildFallibleIterator>; 173 174 class Symbol { 175 const Archive *Parent; 176 uint32_t SymbolIndex; 177 uint32_t StringIndex; // Extra index to the string. 178 179 public: 180 Symbol(const Archive *p, uint32_t symi, uint32_t stri) 181 : Parent(p), SymbolIndex(symi), StringIndex(stri) {} 182 183 bool operator==(const Symbol &other) const { 184 return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); 185 } 186 187 StringRef getName() const; 188 Expected<Child> getMember() const; 189 Symbol getNext() const; 190 }; 191 192 class symbol_iterator { 193 Symbol symbol; 194 195 public: 196 symbol_iterator(const Symbol &s) : symbol(s) {} 197 198 const Symbol *operator->() const { return &symbol; } 199 const Symbol &operator*() const { return symbol; } 200 201 bool operator==(const symbol_iterator &other) const { 202 return symbol == other.symbol; 203 } 204 205 bool operator!=(const symbol_iterator &other) const { 206 return !(*this == other); 207 } 208 209 symbol_iterator &operator++() { // Preincrement 210 symbol = symbol.getNext(); 211 return *this; 212 } 213 }; 214 215 Archive(MemoryBufferRef Source, Error &Err); 216 static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source); 217 218 /// Size field is 10 decimal digits long 219 static const uint64_t MaxMemberSize = 9999999999; 220 221 enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF }; 222 223 Kind kind() const { return (Kind)Format; } 224 bool isThin() const { return IsThin; } 225 226 child_iterator child_begin(Error &Err, bool SkipInternal = true) const; 227 child_iterator child_end() const; 228 iterator_range<child_iterator> children(Error &Err, 229 bool SkipInternal = true) const { 230 return make_range(child_begin(Err, SkipInternal), child_end()); 231 } 232 233 symbol_iterator symbol_begin() const; 234 symbol_iterator symbol_end() const; 235 iterator_range<symbol_iterator> symbols() const { 236 return make_range(symbol_begin(), symbol_end()); 237 } 238 239 // Cast methods. 240 static bool classof(Binary const *v) { return v->isArchive(); } 241 242 // check if a symbol is in the archive 243 Expected<Optional<Child>> findSym(StringRef name) const; 244 245 bool isEmpty() const; 246 bool hasSymbolTable() const; 247 StringRef getSymbolTable() const { return SymbolTable; } 248 StringRef getStringTable() const { return StringTable; } 249 uint32_t getNumberOfSymbols() const; 250 251 std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { 252 return std::move(ThinBuffers); 253 } 254 255 private: 256 StringRef SymbolTable; 257 StringRef StringTable; 258 259 StringRef FirstRegularData; 260 uint16_t FirstRegularStartOfFile = -1; 261 void setFirstRegular(const Child &C); 262 263 unsigned Format : 3; 264 unsigned IsThin : 1; 265 mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; 266 }; 267 268 } // end namespace object 269 } // end namespace llvm 270 271 #endif // LLVM_OBJECT_ARCHIVE_H 272