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