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