Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:17

0001 //===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the ar archive file format class.
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   /// Get the name without looking up long names.
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   /// Get the name looking up long names.
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   /// Get next file member location.
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   /// Returns the size in bytes of the format-defined member header of the
0070   /// concrete archive type.
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]; ///< Size of data, not including header or padding.
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 // File Member Header
0120 struct BigArMemHdrType {
0121   char Size[20];       // File member size in decimal
0122   char NextOffset[20]; // Next member offset in decimal
0123   char PrevOffset[20]; // Previous member offset in decimal
0124   char LastModified[12];
0125   char UID[12];
0126   char GID[12];
0127   char AccessMode[12];
0128   char NameLen[4]; // File member name length in decimal
0129   union {
0130     char Name[2]; // Start of member name
0131     char Terminator[2];
0132   };
0133 };
0134 
0135 // Define file member header of AIX big archive.
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     /// Includes header but not padding byte.
0167     StringRef Data;
0168     /// Offset from Data to the start of the file.
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     /// \return the size of the archive member without the header or padding.
0243     Expected<uint64_t> getSize() const;
0244     /// \return the size in the archive header for this member.
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       // Ignore errors here: If an error occurred during increment then getNext
0269       // will have been set to child_end(), and the following comparison should
0270       // do the right thing.
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; // Extra index to the string.
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++() { // Preincrement
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   /// Size field is 10 decimal digits long
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   // check if a symbol is in the archive
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   /// Fixed-Length Header.
0400   struct FixLenHdr {
0401     char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string.
0402     char MemOffset[20];                      ///< Offset to member table.
0403     char GlobSymOffset[20];                  ///< Offset to global symbol table.
0404     char
0405         GlobSym64Offset[20]; ///< Offset global symbol table for 64-bit objects.
0406     char FirstChildOffset[20]; ///< Offset to first archive member.
0407     char LastChildOffset[20];  ///< Offset to last archive member.
0408     char FreeOffset[20];       ///< Offset to first mem on free list.
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 } // end namespace object
0429 } // end namespace llvm
0430 
0431 #endif // LLVM_OBJECT_ARCHIVE_H