1//===- Archive.h ----------------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#ifndef MCLD_LD_ARCHIVE_H_
10#define MCLD_LD_ARCHIVE_H_
11
12#include "mcld/InputTree.h"
13#include "mcld/ADT/HashEntry.h"
14#include "mcld/ADT/HashTable.h"
15#include "mcld/ADT/StringHash.h"
16#include "mcld/Support/GCFactory.h"
17
18#include <string>
19#include <vector>
20
21namespace mcld {
22
23class Input;
24class InputBuilder;
25class InputFactory;
26
27/** \class Archive
28 *  \brief This class define the interfacee to Archive files
29 */
30class Archive {
31 public:
32  static const char MAGIC[];              ///< magic string
33  static const char THIN_MAGIC[];         ///< magic of thin archive
34  static const size_t MAGIC_LEN;          ///< length of magic string
35  static const char SVR4_SYMTAB_NAME[];   ///< SVR4 symtab entry name
36  static const char IRIX6_SYMTAB_NAME[];  ///< Irix6 symtab entry name
37  static const char STRTAB_NAME[];        ///< Name of string table
38  static const char PAD[];                ///< inter-file align padding
39  static const char MEMBER_MAGIC[];       ///< fmag field magic #
40
41  struct MemberHeader {
42    char name[16];  ///< Name of the file member.
43    char date[12];  ///< File date, decimal seconds since Epoch
44    char uid[6];    ///< user id in ASCII decimal
45    char gid[6];    ///< group id in ASCII decimal
46    char mode[8];   ///< file mode in ASCII octal
47    char size[10];  ///< file size in ASCII decimal
48    char fmag[2];   ///< Always contains ARFILE_MAGIC_TERMINATOR
49  };
50
51 private:
52  template <typename OFFSET_TYPE>
53  struct OffsetCompare {
54    bool operator()(OFFSET_TYPE X, OFFSET_TYPE Y) const { return (X == Y); }
55  };
56
57  struct MurmurHash3 {
58    size_t operator()(uint32_t pKey) const {
59      pKey ^= pKey >> 16;
60      pKey *= 0x85ebca6b;
61      pKey ^= pKey >> 13;
62      pKey *= 0xc2b2ae35;
63      pKey ^= pKey >> 16;
64      return pKey;
65    }
66  };
67
68  typedef HashEntry<uint32_t, InputTree::iterator, OffsetCompare<uint32_t> >
69      ObjectMemberEntryType;
70
71 public:
72  typedef HashTable<ObjectMemberEntryType,
73                    MurmurHash3,
74                    EntryFactory<ObjectMemberEntryType> > ObjectMemberMapType;
75
76  struct ArchiveMember {
77    Input* file;
78    InputTree::iterator lastPos;
79    InputTree::Mover* move;
80  };
81
82 private:
83  typedef HashEntry<const llvm::StringRef,
84                    ArchiveMember,
85                    hash::StringCompare<llvm::StringRef> >
86      ArchiveMemberEntryType;
87
88 public:
89  typedef HashTable<ArchiveMemberEntryType,
90                    hash::StringHash<hash::DJB>,
91                    EntryFactory<ArchiveMemberEntryType> > ArchiveMemberMapType;
92
93  struct Symbol {
94   public:
95    enum Status { Include, Exclude, Unknown };
96
97    Symbol(const char* pName, uint32_t pOffset, enum Status pStatus)
98        : name(pName), fileOffset(pOffset), status(pStatus) {}
99
100    ~Symbol() {}
101
102   public:
103    std::string name;
104    uint32_t fileOffset;
105    enum Status status;
106  };
107
108  typedef std::vector<Symbol*> SymTabType;
109
110 public:
111  Archive(Input& pInputFile, InputBuilder& pBuilder);
112
113  ~Archive();
114
115  /// getARFile - get the Input& of the archive file
116  Input& getARFile();
117
118  /// getARFile - get the Input& of the archive file
119  const Input& getARFile() const;
120
121  /// inputs - get the input tree built from this archive
122  InputTree& inputs();
123
124  /// inputs - get the input tree built from this archive
125  const InputTree& inputs() const;
126
127  /// getObjectMemberMap - get the map that contains the included object files
128  ObjectMemberMapType& getObjectMemberMap();
129
130  /// getObjectMemberMap - get the map that contains the included object files
131  const ObjectMemberMapType& getObjectMemberMap() const;
132
133  /// numOfObjectMember - return the number of included object files
134  size_t numOfObjectMember() const;
135
136  /// addObjectMember - add a object in the object member map
137  /// @param pFileOffset - file offset in symtab represents a object file
138  /// @param pIter - the iterator in the input tree built from this archive
139  bool addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter);
140
141  /// hasObjectMember - check if a object file is included or not
142  /// @param pFileOffset - file offset in symtab represents a object file
143  bool hasObjectMember(uint32_t pFileOffset) const;
144
145  /// getArchiveMemberMap - get the map that contains the included archive files
146  ArchiveMemberMapType& getArchiveMemberMap();
147
148  /// getArchiveMemberMap - get the map that contains the included archive files
149  const ArchiveMemberMapType& getArchiveMemberMap() const;
150
151  /// addArchiveMember - add an archive in the archive member map
152  /// @param pName    - the name of the new archive member
153  /// @param pLastPos - this records the point to insert the next node in the
154  ///                   subtree of this archive member
155  /// @param pMove    - this records the direction to insert the next node in
156  ///                   the subtree of this archive member
157  bool addArchiveMember(const llvm::StringRef& pName,
158                        InputTree::iterator pLastPos,
159                        InputTree::Mover* pMove);
160
161  /// hasArchiveMember - check if an archive file is included or not
162  bool hasArchiveMember(const llvm::StringRef& pName) const;
163
164  /// getArchiveMember - get a archive member
165  ArchiveMember* getArchiveMember(const llvm::StringRef& pName);
166
167  /// getSymbolTable - get the symtab
168  SymTabType& getSymbolTable();
169
170  /// getSymbolTable - get the symtab
171  const SymTabType& getSymbolTable() const;
172
173  /// setSymTabSize - set the memory size of symtab
174  void setSymTabSize(size_t pSize);
175
176  /// getSymTabSize - get the memory size of symtab
177  size_t getSymTabSize() const;
178
179  /// numOfSymbols - return the number of symbols in symtab
180  size_t numOfSymbols() const;
181
182  /// addSymbol - add a symtab entry to symtab
183  /// @param pName - symbol name
184  /// @param pFileOffset - file offset in symtab represents a object file
185  void addSymbol(const char* pName,
186                 uint32_t pFileOffset,
187                 enum Symbol::Status pStatus = Archive::Symbol::Unknown);
188
189  /// getSymbolName - get the symbol name with the given index
190  const std::string& getSymbolName(size_t pSymIdx) const;
191
192  /// getObjFileOffset - get the file offset that represent a object file
193  uint32_t getObjFileOffset(size_t pSymIdx) const;
194
195  /// getSymbolStatus - get the status of a symbol
196  enum Symbol::Status getSymbolStatus(size_t pSymIdx) const;
197
198  /// setSymbolStatus - set the status of a symbol
199  void setSymbolStatus(size_t pSymIdx, enum Symbol::Status pStatus);
200
201  /// getStrTable - get the extended name table
202  std::string& getStrTable();
203
204  /// getStrTable - get the extended name table
205  const std::string& getStrTable() const;
206
207  /// hasStrTable - return true if this archive has extended name table
208  bool hasStrTable() const;
209
210  /// getMemberFile       - get the member file in an archive member
211  /// @param pArchiveFile - Input reference of the archive member
212  /// @param pIsThinAR    - denote the archive menber is a Thin Archive or not
213  /// @param pName        - the name of the member file we want to get
214  /// @param pPath        - the path of the member file
215  /// @param pFileOffset  - the file offset of the member file in a regular AR
216  Input* getMemberFile(Input& pArchiveFile,
217                       bool isThinAR,
218                       const std::string& pName,
219                       const sys::fs::Path& pPath,
220                       off_t pFileOffset = 0);
221
222 private:
223  typedef GCFactory<Symbol, 0> SymbolFactory;
224
225 private:
226  Input& m_ArchiveFile;
227  InputTree* m_pInputTree;
228  ObjectMemberMapType m_ObjectMemberMap;
229  ArchiveMemberMapType m_ArchiveMemberMap;
230  SymbolFactory m_SymbolFactory;
231  SymTabType m_SymTab;
232  size_t m_SymTabSize;
233  std::string m_StrTab;
234  InputBuilder& m_Builder;
235};
236
237}  // namespace mcld
238
239#endif  // MCLD_LD_ARCHIVE_H_
240