File indexing completed on 2026-05-10 08:44:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_OBJECT_ARCHIVE_H
0014 #define LLVM_OBJECT_ARCHIVE_H
0015
0016 #include "llvm/ADT/StringRef.h"
0017 #include "llvm/ADT/fallible_iterator.h"
0018 #include "llvm/ADT/iterator_range.h"
0019 #include "llvm/Object/Binary.h"
0020 #include "llvm/Support/Chrono.h"
0021 #include "llvm/Support/Error.h"
0022 #include "llvm/Support/FileSystem.h"
0023 #include "llvm/Support/MemoryBuffer.h"
0024 #include <cassert>
0025 #include <cstdint>
0026 #include <memory>
0027 #include <string>
0028 #include <vector>
0029
0030 namespace llvm {
0031 namespace object {
0032
0033 const char ArchiveMagic[] = "!<arch>\n";
0034 const char ThinArchiveMagic[] = "!<thin>\n";
0035 const char BigArchiveMagic[] = "<bigaf>\n";
0036
0037 class Archive;
0038
0039 class AbstractArchiveMemberHeader {
0040 protected:
0041 AbstractArchiveMemberHeader(const Archive *Parent) : Parent(Parent){};
0042
0043 public:
0044 friend class Archive;
0045 virtual std::unique_ptr<AbstractArchiveMemberHeader> clone() const = 0;
0046 virtual ~AbstractArchiveMemberHeader() = default;
0047
0048
0049 virtual Expected<StringRef> getRawName() const = 0;
0050 virtual StringRef getRawAccessMode() const = 0;
0051 virtual StringRef getRawLastModified() const = 0;
0052 virtual StringRef getRawUID() const = 0;
0053 virtual StringRef getRawGID() const = 0;
0054
0055
0056 virtual Expected<StringRef> getName(uint64_t Size) const = 0;
0057 virtual Expected<uint64_t> getSize() const = 0;
0058 virtual uint64_t getOffset() const = 0;
0059
0060
0061 virtual Expected<const char *> getNextChildLoc() const = 0;
0062 virtual Expected<bool> isThin() const = 0;
0063
0064 Expected<sys::fs::perms> getAccessMode() const;
0065 Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
0066 Expected<unsigned> getUID() const;
0067 Expected<unsigned> getGID() const;
0068
0069
0070
0071 virtual uint64_t getSizeOf() const = 0;
0072
0073 const Archive *Parent;
0074 };
0075
0076 template <typename T>
0077 class CommonArchiveMemberHeader : public AbstractArchiveMemberHeader {
0078 public:
0079 CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr)
0080 : AbstractArchiveMemberHeader(Parent), ArMemHdr(RawHeaderPtr){};
0081 StringRef getRawAccessMode() const override;
0082 StringRef getRawLastModified() const override;
0083 StringRef getRawUID() const override;
0084 StringRef getRawGID() const override;
0085
0086 uint64_t getOffset() const override;
0087 uint64_t getSizeOf() const override { return sizeof(T); }
0088
0089 T const *ArMemHdr;
0090 };
0091
0092 struct UnixArMemHdrType {
0093 char Name[16];
0094 char LastModified[12];
0095 char UID[6];
0096 char GID[6];
0097 char AccessMode[8];
0098 char Size[10];
0099 char Terminator[2];
0100 };
0101
0102 class ArchiveMemberHeader : public CommonArchiveMemberHeader<UnixArMemHdrType> {
0103 public:
0104 ArchiveMemberHeader(const Archive *Parent, const char *RawHeaderPtr,
0105 uint64_t Size, Error *Err);
0106
0107 std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
0108 return std::make_unique<ArchiveMemberHeader>(*this);
0109 }
0110
0111 Expected<StringRef> getRawName() const override;
0112
0113 Expected<StringRef> getName(uint64_t Size) const override;
0114 Expected<uint64_t> getSize() const override;
0115 Expected<const char *> getNextChildLoc() const override;
0116 Expected<bool> isThin() const override;
0117 };
0118
0119
0120 struct BigArMemHdrType {
0121 char Size[20];
0122 char NextOffset[20];
0123 char PrevOffset[20];
0124 char LastModified[12];
0125 char UID[12];
0126 char GID[12];
0127 char AccessMode[12];
0128 char NameLen[4];
0129 union {
0130 char Name[2];
0131 char Terminator[2];
0132 };
0133 };
0134
0135
0136 class BigArchiveMemberHeader
0137 : public CommonArchiveMemberHeader<BigArMemHdrType> {
0138
0139 public:
0140 BigArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
0141 uint64_t Size, Error *Err);
0142 std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
0143 return std::make_unique<BigArchiveMemberHeader>(*this);
0144 }
0145
0146 Expected<StringRef> getRawName() const override;
0147 Expected<uint64_t> getRawNameSize() const;
0148
0149 Expected<StringRef> getName(uint64_t Size) const override;
0150 Expected<uint64_t> getSize() const override;
0151 Expected<const char *> getNextChildLoc() const override;
0152 Expected<uint64_t> getNextOffset() const;
0153 Expected<bool> isThin() const override { return false; }
0154 };
0155
0156 class Archive : public Binary {
0157 virtual void anchor();
0158
0159 public:
0160 class Child {
0161 friend Archive;
0162 friend AbstractArchiveMemberHeader;
0163
0164 const Archive *Parent;
0165 std::unique_ptr<AbstractArchiveMemberHeader> Header;
0166
0167 StringRef Data;
0168
0169 uint16_t StartOfFile;
0170
0171 Expected<bool> isThinMember() const;
0172
0173 public:
0174 Child(const Archive *Parent, const char *Start, Error *Err);
0175 Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);
0176
0177 Child(const Child &C)
0178 : Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile) {
0179 if (C.Header)
0180 Header = C.Header->clone();
0181 }
0182
0183 Child(Child &&C) {
0184 Parent = std::move(C.Parent);
0185 Header = std::move(C.Header);
0186 Data = C.Data;
0187 StartOfFile = C.StartOfFile;
0188 }
0189
0190 Child &operator=(Child &&C) noexcept {
0191 if (&C == this)
0192 return *this;
0193
0194 Parent = std::move(C.Parent);
0195 Header = std::move(C.Header);
0196 Data = C.Data;
0197 StartOfFile = C.StartOfFile;
0198
0199 return *this;
0200 }
0201
0202 Child &operator=(const Child &C) {
0203 if (&C == this)
0204 return *this;
0205
0206 Parent = C.Parent;
0207 if (C.Header)
0208 Header = C.Header->clone();
0209 Data = C.Data;
0210 StartOfFile = C.StartOfFile;
0211
0212 return *this;
0213 }
0214
0215 bool operator==(const Child &other) const {
0216 assert(!Parent || !other.Parent || Parent == other.Parent);
0217 return Data.begin() == other.Data.begin();
0218 }
0219
0220 const Archive *getParent() const { return Parent; }
0221 Expected<Child> getNext() const;
0222
0223 Expected<StringRef> getName() const;
0224 Expected<std::string> getFullName() const;
0225 Expected<StringRef> getRawName() const { return Header->getRawName(); }
0226
0227 Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const {
0228 return Header->getLastModified();
0229 }
0230
0231 StringRef getRawLastModified() const {
0232 return Header->getRawLastModified();
0233 }
0234
0235 Expected<unsigned> getUID() const { return Header->getUID(); }
0236 Expected<unsigned> getGID() const { return Header->getGID(); }
0237
0238 Expected<sys::fs::perms> getAccessMode() const {
0239 return Header->getAccessMode();
0240 }
0241
0242
0243 Expected<uint64_t> getSize() const;
0244
0245 Expected<uint64_t> getRawSize() const;
0246
0247 Expected<StringRef> getBuffer() const;
0248 uint64_t getChildOffset() const;
0249 uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
0250
0251 Expected<MemoryBufferRef> getMemoryBufferRef() const;
0252
0253 Expected<std::unique_ptr<Binary>>
0254 getAsBinary(LLVMContext *Context = nullptr) const;
0255 };
0256
0257 class ChildFallibleIterator {
0258 Child C;
0259
0260 public:
0261 ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {}
0262 ChildFallibleIterator(const Child &C) : C(C) {}
0263
0264 const Child *operator->() const { return &C; }
0265 const Child &operator*() const { return C; }
0266
0267 bool operator==(const ChildFallibleIterator &other) const {
0268
0269
0270
0271 return C == other.C;
0272 }
0273
0274 bool operator!=(const ChildFallibleIterator &other) const {
0275 return !(*this == other);
0276 }
0277
0278 Error inc() {
0279 auto NextChild = C.getNext();
0280 if (!NextChild)
0281 return NextChild.takeError();
0282 C = std::move(*NextChild);
0283 return Error::success();
0284 }
0285 };
0286
0287 using child_iterator = fallible_iterator<ChildFallibleIterator>;
0288
0289 class Symbol {
0290 const Archive *Parent;
0291 uint32_t SymbolIndex;
0292 uint32_t StringIndex;
0293
0294 public:
0295 Symbol(const Archive *p, uint32_t symi, uint32_t stri)
0296 : Parent(p), SymbolIndex(symi), StringIndex(stri) {}
0297
0298 bool operator==(const Symbol &other) const {
0299 return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
0300 }
0301
0302 StringRef getName() const;
0303 Expected<Child> getMember() const;
0304 Symbol getNext() const;
0305 bool isECSymbol() const;
0306 };
0307
0308 class symbol_iterator {
0309 Symbol symbol;
0310
0311 public:
0312 symbol_iterator(const Symbol &s) : symbol(s) {}
0313
0314 const Symbol *operator->() const { return &symbol; }
0315 const Symbol &operator*() const { return symbol; }
0316
0317 bool operator==(const symbol_iterator &other) const {
0318 return symbol == other.symbol;
0319 }
0320
0321 bool operator!=(const symbol_iterator &other) const {
0322 return !(*this == other);
0323 }
0324
0325 symbol_iterator &operator++() {
0326 symbol = symbol.getNext();
0327 return *this;
0328 }
0329 };
0330
0331 Archive(MemoryBufferRef Source, Error &Err);
0332 static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
0333
0334
0335 static const uint64_t MaxMemberSize = 9999999999;
0336
0337 enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF, K_AIXBIG };
0338
0339 Kind kind() const { return (Kind)Format; }
0340 bool isThin() const { return IsThin; }
0341 static object::Archive::Kind getDefaultKind();
0342 static object::Archive::Kind getDefaultKindForTriple(const Triple &T);
0343
0344 child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
0345 child_iterator child_end() const;
0346 iterator_range<child_iterator> children(Error &Err,
0347 bool SkipInternal = true) const {
0348 return make_range(child_begin(Err, SkipInternal), child_end());
0349 }
0350
0351 symbol_iterator symbol_begin() const;
0352 symbol_iterator symbol_end() const;
0353 iterator_range<symbol_iterator> symbols() const {
0354 return make_range(symbol_begin(), symbol_end());
0355 }
0356
0357 Expected<iterator_range<symbol_iterator>> ec_symbols() const;
0358
0359 static bool classof(Binary const *v) { return v->isArchive(); }
0360
0361
0362 Expected<std::optional<Child>> findSym(StringRef name) const;
0363
0364 virtual bool isEmpty() const;
0365 bool hasSymbolTable() const;
0366 StringRef getSymbolTable() const { return SymbolTable; }
0367 StringRef getStringTable() const { return StringTable; }
0368 uint32_t getNumberOfSymbols() const;
0369 uint32_t getNumberOfECSymbols() const;
0370 virtual uint64_t getFirstChildOffset() const { return getArchiveMagicLen(); }
0371
0372 std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
0373 return std::move(ThinBuffers);
0374 }
0375
0376 std::unique_ptr<AbstractArchiveMemberHeader>
0377 createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
0378 Error *Err) const;
0379
0380 protected:
0381 uint64_t getArchiveMagicLen() const;
0382 void setFirstRegular(const Child &C);
0383
0384 StringRef SymbolTable;
0385 StringRef ECSymbolTable;
0386 StringRef StringTable;
0387
0388 private:
0389 StringRef FirstRegularData;
0390 uint16_t FirstRegularStartOfFile = -1;
0391
0392 unsigned Format : 3;
0393 unsigned IsThin : 1;
0394 mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
0395 };
0396
0397 class BigArchive : public Archive {
0398 public:
0399
0400 struct FixLenHdr {
0401 char Magic[sizeof(BigArchiveMagic) - 1];
0402 char MemOffset[20];
0403 char GlobSymOffset[20];
0404 char
0405 GlobSym64Offset[20];
0406 char FirstChildOffset[20];
0407 char LastChildOffset[20];
0408 char FreeOffset[20];
0409 };
0410
0411 const FixLenHdr *ArFixLenHdr;
0412 uint64_t FirstChildOffset = 0;
0413 uint64_t LastChildOffset = 0;
0414 std::string MergedGlobalSymtabBuf;
0415 bool Has32BitGlobalSymtab = false;
0416 bool Has64BitGlobalSymtab = false;
0417
0418 public:
0419 BigArchive(MemoryBufferRef Source, Error &Err);
0420 uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
0421 uint64_t getLastChildOffset() const { return LastChildOffset; }
0422 bool isEmpty() const override { return getFirstChildOffset() == 0; }
0423
0424 bool has32BitGlobalSymtab() { return Has32BitGlobalSymtab; }
0425 bool has64BitGlobalSymtab() { return Has64BitGlobalSymtab; }
0426 };
0427
0428 }
0429 }
0430
0431 #endif