1226584Sdim//===- Archive.h - ar archive file format -----------------------*- C++ -*-===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This file declares the ar archive file format class. 11226584Sdim// 12226584Sdim//===----------------------------------------------------------------------===// 13226584Sdim 14226584Sdim#ifndef LLVM_OBJECT_ARCHIVE_H 15226584Sdim#define LLVM_OBJECT_ARCHIVE_H 16226584Sdim 17249423Sdim#include "llvm/ADT/StringRef.h" 18226584Sdim#include "llvm/Object/Binary.h" 19249423Sdim#include "llvm/Support/ErrorHandling.h" 20263508Sdim#include "llvm/Support/FileSystem.h" 21249423Sdim#include "llvm/Support/MemoryBuffer.h" 22226584Sdim 23226584Sdimnamespace llvm { 24226584Sdimnamespace object { 25249423Sdimstruct ArchiveMemberHeader { 26249423Sdim char Name[16]; 27249423Sdim char LastModified[12]; 28249423Sdim char UID[6]; 29249423Sdim char GID[6]; 30249423Sdim char AccessMode[8]; 31249423Sdim char Size[10]; ///< Size of data, not including header or padding. 32249423Sdim char Terminator[2]; 33226584Sdim 34263508Sdim /// Get the name without looking up long names. 35263508Sdim llvm::StringRef getName() const; 36249423Sdim 37263508Sdim /// Members are not larger than 4GB. 38263508Sdim uint32_t getSize() const; 39263508Sdim 40263508Sdim sys::fs::perms getAccessMode() const; 41263508Sdim sys::TimeValue getLastModified() const; 42263508Sdim unsigned getUID() const; 43263508Sdim unsigned getGID() const; 44249423Sdim}; 45249423Sdim 46226584Sdimclass Archive : public Binary { 47234353Sdim virtual void anchor(); 48226584Sdimpublic: 49226584Sdim class Child { 50226584Sdim const Archive *Parent; 51249423Sdim /// \brief Includes header but not padding byte. 52226584Sdim StringRef Data; 53249423Sdim /// \brief Offset from Data to the start of the file. 54249423Sdim uint16_t StartOfFile; 55226584Sdim 56263508Sdim const ArchiveMemberHeader *getHeader() const { 57263508Sdim return reinterpret_cast<const ArchiveMemberHeader *>(Data.data()); 58249423Sdim } 59226584Sdim 60263508Sdim public: 61263508Sdim Child(const Archive *Parent, const char *Start); 62263508Sdim 63226584Sdim bool operator ==(const Child &other) const { 64263508Sdim assert(Parent == other.Parent); 65263508Sdim return Data.begin() == other.Data.begin(); 66226584Sdim } 67226584Sdim 68234353Sdim bool operator <(const Child &other) const { 69234353Sdim return Data.begin() < other.Data.begin(); 70234353Sdim } 71234353Sdim 72263508Sdim Child getNext() const; 73249423Sdim 74263508Sdim error_code getName(StringRef &Result) const; 75263508Sdim StringRef getRawName() const { return getHeader()->getName(); } 76263508Sdim sys::TimeValue getLastModified() const { 77263508Sdim return getHeader()->getLastModified(); 78249423Sdim } 79263508Sdim unsigned getUID() const { return getHeader()->getUID(); } 80263508Sdim unsigned getGID() const { return getHeader()->getGID(); } 81263508Sdim sys::fs::perms getAccessMode() const { 82263508Sdim return getHeader()->getAccessMode(); 83263508Sdim } 84249423Sdim /// \return the size of the archive member without the header or padding. 85249423Sdim uint64_t getSize() const { return Data.size() - StartOfFile; } 86226584Sdim 87249423Sdim StringRef getBuffer() const { 88249423Sdim return StringRef(Data.data() + StartOfFile, getSize()); 89249423Sdim } 90249423Sdim 91249423Sdim error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, 92263508Sdim bool FullPath = false) const; 93249423Sdim 94226584Sdim error_code getAsBinary(OwningPtr<Binary> &Result) const; 95226584Sdim }; 96226584Sdim 97226584Sdim class child_iterator { 98226584Sdim Child child; 99226584Sdim public: 100263508Sdim child_iterator() : child(Child(0, 0)) {} 101226584Sdim child_iterator(const Child &c) : child(c) {} 102226584Sdim const Child* operator->() const { 103226584Sdim return &child; 104226584Sdim } 105226584Sdim 106226584Sdim bool operator==(const child_iterator &other) const { 107226584Sdim return child == other.child; 108226584Sdim } 109226584Sdim 110226584Sdim bool operator!=(const child_iterator &other) const { 111226584Sdim return !(*this == other); 112226584Sdim } 113226584Sdim 114234353Sdim bool operator <(const child_iterator &other) const { 115234353Sdim return child < other.child; 116234353Sdim } 117234353Sdim 118226584Sdim child_iterator& operator++() { // Preincrement 119226584Sdim child = child.getNext(); 120226584Sdim return *this; 121226584Sdim } 122226584Sdim }; 123226584Sdim 124234353Sdim class Symbol { 125234353Sdim const Archive *Parent; 126234353Sdim uint32_t SymbolIndex; 127234353Sdim uint32_t StringIndex; // Extra index to the string. 128234353Sdim 129234353Sdim public: 130234353Sdim bool operator ==(const Symbol &other) const { 131234353Sdim return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); 132234353Sdim } 133234353Sdim 134234353Sdim Symbol(const Archive *p, uint32_t symi, uint32_t stri) 135234353Sdim : Parent(p) 136234353Sdim , SymbolIndex(symi) 137234353Sdim , StringIndex(stri) {} 138234353Sdim error_code getName(StringRef &Result) const; 139234353Sdim error_code getMember(child_iterator &Result) const; 140234353Sdim Symbol getNext() const; 141234353Sdim }; 142234353Sdim 143234353Sdim class symbol_iterator { 144234353Sdim Symbol symbol; 145234353Sdim public: 146234353Sdim symbol_iterator(const Symbol &s) : symbol(s) {} 147234353Sdim const Symbol *operator->() const { 148234353Sdim return &symbol; 149234353Sdim } 150234353Sdim 151234353Sdim bool operator==(const symbol_iterator &other) const { 152234353Sdim return symbol == other.symbol; 153234353Sdim } 154234353Sdim 155234353Sdim bool operator!=(const symbol_iterator &other) const { 156234353Sdim return !(*this == other); 157234353Sdim } 158234353Sdim 159234353Sdim symbol_iterator& operator++() { // Preincrement 160234353Sdim symbol = symbol.getNext(); 161234353Sdim return *this; 162234353Sdim } 163234353Sdim }; 164234353Sdim 165226584Sdim Archive(MemoryBuffer *source, error_code &ec); 166226584Sdim 167249423Sdim enum Kind { 168249423Sdim K_GNU, 169249423Sdim K_BSD, 170249423Sdim K_COFF 171249423Sdim }; 172249423Sdim 173249423Sdim Kind kind() const { 174249423Sdim return Format; 175249423Sdim } 176249423Sdim 177263508Sdim child_iterator begin_children(bool SkipInternal = true) const; 178226584Sdim child_iterator end_children() const; 179226584Sdim 180234353Sdim symbol_iterator begin_symbols() const; 181234353Sdim symbol_iterator end_symbols() const; 182234353Sdim 183226584Sdim // Cast methods. 184226584Sdim static inline bool classof(Binary const *v) { 185234353Sdim return v->isArchive(); 186226584Sdim } 187226584Sdim 188249423Sdim // check if a symbol is in the archive 189249423Sdim child_iterator findSym(StringRef name) const; 190249423Sdim 191263508Sdim bool hasSymbolTable() const; 192263508Sdim 193226584Sdimprivate: 194234353Sdim child_iterator SymbolTable; 195226584Sdim child_iterator StringTable; 196263508Sdim child_iterator FirstRegular; 197249423Sdim Kind Format; 198226584Sdim}; 199226584Sdim 200226584Sdim} 201226584Sdim} 202226584Sdim 203226584Sdim#endif 204