aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/Object/Archive.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include/llvm/Object/Archive.h')
-rw-r--r--llvm/include/llvm/Object/Archive.h219
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