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 
21 namespace mcld {
22 
23 class Input;
24 class InputBuilder;
25 class InputFactory;
26 
27 /** \class Archive
28  *  \brief This class define the interfacee to Archive files
29  */
30 class 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 {
operatorOffsetCompare54     bool operator()(OFFSET_TYPE X, OFFSET_TYPE Y) const { return (X == Y); }
55   };
56 
57   struct MurmurHash3 {
operatorMurmurHash358     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 
SymbolSymbol97     Symbol(const char* pName, uint32_t pOffset, enum Status pStatus)
98         : name(pName), fileOffset(pOffset), status(pStatus) {}
99 
~SymbolSymbol100     ~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