diff options
Diffstat (limited to 'llvm/include/llvm/Object/Archive.h')
-rw-r--r-- | llvm/include/llvm/Object/Archive.h | 219 |
1 files changed, 183 insertions, 36 deletions
diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index 5b024c7baebc..5a5fc90f18bd 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -32,50 +32,127 @@ namespace llvm { namespace object { +const char ArchiveMagic[] = "!<arch>\n"; +const char ThinArchiveMagic[] = "!<thin>\n"; +const char BigArchiveMagic[] = "<bigaf>\n"; + class Archive; -class ArchiveMemberHeader { +class AbstractArchiveMemberHeader { +protected: + AbstractArchiveMemberHeader(const Archive *Parent) : Parent(Parent){}; + public: friend class Archive; - - ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr, - uint64_t Size, Error *Err); - // ArchiveMemberHeader() = default; + virtual std::unique_ptr<AbstractArchiveMemberHeader> clone() const = 0; + virtual ~AbstractArchiveMemberHeader(){}; /// Get the name without looking up long names. - Expected<StringRef> getRawName() const; + virtual Expected<StringRef> getRawName() const = 0; + virtual StringRef getRawAccessMode() const = 0; + virtual StringRef getRawLastModified() const = 0; + virtual StringRef getRawUID() const = 0; + virtual StringRef getRawGID() const = 0; /// Get the name looking up long names. - Expected<StringRef> getName(uint64_t Size) const; + virtual Expected<StringRef> getName(uint64_t Size) const = 0; + virtual Expected<uint64_t> getSize() const = 0; + virtual uint64_t getOffset() const = 0; - Expected<uint64_t> getSize() const; + /// Get next file member location. + virtual Expected<const char *> getNextChildLoc() const = 0; + virtual Expected<bool> isThin() const = 0; Expected<sys::fs::perms> getAccessMode() const; Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const; + Expected<unsigned> getUID() const; + Expected<unsigned> getGID() const; + + /// Returns the size in bytes of the format-defined member header of the + /// concrete archive type. + virtual uint64_t getSizeOf() const = 0; + + const Archive *Parent; +}; + +template <typename T> +class CommonArchiveMemberHeader : public AbstractArchiveMemberHeader { +public: + CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr) + : AbstractArchiveMemberHeader(Parent), ArMemHdr(RawHeaderPtr){}; + StringRef getRawAccessMode() const override; + StringRef getRawLastModified() const override; + StringRef getRawUID() const override; + StringRef getRawGID() const override; + + uint64_t getOffset() const override; + uint64_t getSizeOf() const override { return sizeof(T); } + + T const *ArMemHdr; +}; - StringRef getRawLastModified() const { - return StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified)) - .rtrim(' '); +struct UnixArMemHdrType { + char Name[16]; + char LastModified[12]; + char UID[6]; + char GID[6]; + char AccessMode[8]; + char Size[10]; ///< Size of data, not including header or padding. + char Terminator[2]; +}; + +class ArchiveMemberHeader : public CommonArchiveMemberHeader<UnixArMemHdrType> { +public: + ArchiveMemberHeader(const Archive *Parent, const char *RawHeaderPtr, + uint64_t Size, Error *Err); + + std::unique_ptr<AbstractArchiveMemberHeader> clone() const override { + return std::make_unique<ArchiveMemberHeader>(*this); } - Expected<unsigned> getUID() const; - Expected<unsigned> getGID() const; + Expected<StringRef> getRawName() const override; - // This returns the size of the private struct ArMemHdrType - uint64_t getSizeOf() const { return sizeof(ArMemHdrType); } + Expected<StringRef> getName(uint64_t Size) const override; + Expected<uint64_t> getSize() const override; + Expected<const char *> getNextChildLoc() const override; + Expected<bool> isThin() const override; +}; -private: - struct ArMemHdrType { - char Name[16]; - char LastModified[12]; - char UID[6]; - char GID[6]; - char AccessMode[8]; - char Size[10]; ///< Size of data, not including header or padding. +// File Member Header +struct BigArMemHdrType { + char Size[20]; // File member size in decimal + char NextOffset[20]; // Next member offset in decimal + char PrevOffset[20]; // Previous member offset in decimal + char LastModified[12]; + char UID[12]; + char GID[12]; + char AccessMode[12]; + char NameLen[4]; // File member name length in decimal + union { + char Name[2]; // Start of member name char Terminator[2]; }; - Archive const *Parent; - ArMemHdrType const *ArMemHdr; +}; + +// Define file member header of AIX big archive. +class BigArchiveMemberHeader + : public CommonArchiveMemberHeader<BigArMemHdrType> { + +public: + BigArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr, + uint64_t Size, Error *Err); + std::unique_ptr<AbstractArchiveMemberHeader> clone() const override { + return std::make_unique<BigArchiveMemberHeader>(*this); + } + + Expected<StringRef> getRawName() const override; + Expected<uint64_t> getRawNameSize() const; + + Expected<StringRef> getName(uint64_t Size) const override; + Expected<uint64_t> getSize() const override; + Expected<const char *> getNextChildLoc() const override; + Expected<uint64_t> getNextOffset() const; + Expected<bool> isThin() const override { return false; } }; class Archive : public Binary { @@ -84,10 +161,10 @@ class Archive : public Binary { public: class Child { friend Archive; - friend ArchiveMemberHeader; + friend AbstractArchiveMemberHeader; const Archive *Parent; - ArchiveMemberHeader Header; + std::unique_ptr<AbstractArchiveMemberHeader> Header; /// Includes header but not padding byte. StringRef Data; /// Offset from Data to the start of the file. @@ -99,6 +176,44 @@ public: Child(const Archive *Parent, const char *Start, Error *Err); Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); + Child(const Child &C) + : Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile) { + if (C.Header) + Header = C.Header->clone(); + } + + Child(Child &&C) { + Parent = std::move(C.Parent); + Header = std::move(C.Header); + Data = C.Data; + StartOfFile = C.StartOfFile; + } + + Child &operator=(Child &&C) noexcept { + if (&C == this) + return *this; + + Parent = std::move(C.Parent); + Header = std::move(C.Header); + Data = C.Data; + StartOfFile = C.StartOfFile; + + return *this; + } + + Child &operator=(const Child &C) { + if (&C == this) + return *this; + + Parent = C.Parent; + if (C.Header) + Header = C.Header->clone(); + Data = C.Data; + StartOfFile = C.StartOfFile; + + return *this; + } + bool operator==(const Child &other) const { assert(!Parent || !other.Parent || Parent == other.Parent); return Data.begin() == other.Data.begin(); @@ -109,19 +224,21 @@ public: Expected<StringRef> getName() const; Expected<std::string> getFullName() const; - Expected<StringRef> getRawName() const { return Header.getRawName(); } + Expected<StringRef> getRawName() const { return Header->getRawName(); } Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const { - return Header.getLastModified(); + return Header->getLastModified(); } - StringRef getRawLastModified() const { return Header.getRawLastModified(); } + StringRef getRawLastModified() const { + return Header->getRawLastModified(); + } - Expected<unsigned> getUID() const { return Header.getUID(); } - Expected<unsigned> getGID() const { return Header.getGID(); } + Expected<unsigned> getUID() const { return Header->getUID(); } + Expected<unsigned> getGID() const { return Header->getGID(); } Expected<sys::fs::perms> getAccessMode() const { - return Header.getAccessMode(); + return Header->getAccessMode(); } /// \return the size of the archive member without the header or padding. @@ -218,7 +335,7 @@ public: /// Size field is 10 decimal digits long static const uint64_t MaxMemberSize = 9999999999; - enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF }; + enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF, K_AIXBIG }; Kind kind() const { return (Kind)Format; } bool isThin() const { return IsThin; } @@ -236,7 +353,6 @@ public: return make_range(symbol_begin(), symbol_end()); } - // Cast methods. static bool classof(Binary const *v) { return v->isArchive(); } // check if a symbol is in the archive @@ -247,24 +363,55 @@ public: StringRef getSymbolTable() const { return SymbolTable; } StringRef getStringTable() const { return StringTable; } uint32_t getNumberOfSymbols() const; + virtual uint64_t getFirstChildOffset() const { return getArchiveMagicLen(); } std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { return std::move(ThinBuffers); } + std::unique_ptr<AbstractArchiveMemberHeader> + createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size, + Error *Err) const; + +protected: + uint64_t getArchiveMagicLen() const; + void setFirstRegular(const Child &C); + private: StringRef SymbolTable; StringRef StringTable; StringRef FirstRegularData; uint16_t FirstRegularStartOfFile = -1; - void setFirstRegular(const Child &C); unsigned Format : 3; unsigned IsThin : 1; mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; }; +class BigArchive : public Archive { + /// Fixed-Length Header. + struct FixLenHdr { + char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string. + char MemOffset[20]; ///< Offset to member table. + char GlobSymOffset[20]; ///< Offset to global symbol table. + char + GlobSym64Offset[20]; ///< Offset global symbol table for 64-bit objects. + char FirstChildOffset[20]; ///< Offset to first archive member. + char LastChildOffset[20]; ///< Offset to last archive member. + char FreeOffset[20]; ///< Offset to first mem on free list. + }; + + const FixLenHdr *ArFixLenHdr; + uint64_t FirstChildOffset = 0; + uint64_t LastChildOffset = 0; + +public: + BigArchive(MemoryBufferRef Source, Error &Err); + uint64_t getFirstChildOffset() const override { return FirstChildOffset; } + uint64_t getLastChildOffset() const { return LastChildOffset; } +}; + } // end namespace object } // end namespace llvm |