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