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