• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Archive.cpp --------------------------------------------------------===//
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 #include <mcld/LD/Archive.h>
10 #include <mcld/MC/InputBuilder.h>
11 #include <mcld/MC/Input.h>
12 #include <llvm/ADT/StringRef.h>
13 #include <mcld/Support/MsgHandling.h>
14 
15 using namespace mcld;
16 
17 //===----------------------------------------------------------------------===//
18 // Archive
19 const char   Archive::MAGIC[]            = "!<arch>\n";
20 const char   Archive::THIN_MAGIC[]       = "!<thin>\n";
21 const size_t Archive::MAGIC_LEN          = sizeof(Archive::MAGIC) - 1;
22 const char   Archive::SVR4_SYMTAB_NAME[] = "/               ";
23 const char   Archive::IRIX6_SYMTAB_NAME[]= "/SYM64/         ";
24 const char   Archive::STRTAB_NAME[]      = "//              ";
25 const char   Archive::PAD[]              = "\n";
26 const char   Archive::MEMBER_MAGIC[]     = "`\n";
27 
Archive(Input & pInputFile,InputBuilder & pBuilder)28 Archive::Archive(Input& pInputFile, InputBuilder& pBuilder)
29  : m_ArchiveFile(pInputFile),
30    m_pInputTree(NULL),
31    m_SymbolFactory(32),
32    m_Builder(pBuilder)
33 {
34   // FIXME: move creation of input tree out of Archive.
35   m_pInputTree = new InputTree();
36 }
37 
~Archive()38 Archive::~Archive()
39 {
40   delete m_pInputTree;
41 }
42 
43 /// getARFile - get the Input& of the archive file
getARFile()44 Input& Archive::getARFile()
45 {
46   return m_ArchiveFile;
47 }
48 
49 /// getARFile - get the Input& of the archive file
getARFile() const50 const Input& Archive::getARFile() const
51 {
52   return m_ArchiveFile;
53 }
54 
55 /// inputs - get the input tree built from this archive
inputs()56 InputTree& Archive::inputs()
57 {
58   return *m_pInputTree;
59 }
60 
61 /// inputs - get the input tree built from this archive
inputs() const62 const InputTree& Archive::inputs() const
63 {
64   return *m_pInputTree;
65 }
66 
67 /// getObjectMemberMap - get the map that contains the included object files
getObjectMemberMap()68 Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
69 {
70   return m_ObjectMemberMap;
71 }
72 
73 /// getObjectMemberMap - get the map that contains the included object files
getObjectMemberMap() const74 const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
75 {
76   return m_ObjectMemberMap;
77 }
78 
79 /// numOfObjectMember - return the number of included object files
numOfObjectMember() const80 size_t Archive::numOfObjectMember() const
81 {
82   return m_ObjectMemberMap.numOfEntries();
83 }
84 
85 /// addObjectMember - add a object in the object member map
86 /// @param pFileOffset - file offset in symtab represents a object file
87 /// @param pIter - the iterator in the input tree built from this archive
addObjectMember(uint32_t pFileOffset,InputTree::iterator pIter)88 bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter)
89 {
90   bool exist;
91   ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist);
92   if (!exist)
93     entry->setValue(pIter);
94   return !exist;
95 }
96 
97 /// hasObjectMember - check if a object file is included or not
98 /// @param pFileOffset - file offset in symtab represents a object file
hasObjectMember(uint32_t pFileOffset) const99 bool Archive::hasObjectMember(uint32_t pFileOffset) const
100 {
101   return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end());
102 }
103 
104 /// getArchiveMemberMap - get the map that contains the included archive files
getArchiveMemberMap()105 Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
106 {
107   return m_ArchiveMemberMap;
108 }
109 
110 /// getArchiveMemberMap - get the map that contains the included archive files
getArchiveMemberMap() const111 const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const
112 {
113   return m_ArchiveMemberMap;
114 }
115 
116 /// addArchiveMember - add an archive in the archive member map
117 /// @param pName    - the name of the new archive member
118 /// @param pLastPos - this records the point to insert the next node in the
119 ///                   subtree of this archive member
120 /// @param pMove    - this records the direction to insert the next node in the
121 ///                   subtree of this archive member
addArchiveMember(const llvm::StringRef & pName,InputTree::iterator pLastPos,InputTree::Mover * pMove)122 bool Archive::addArchiveMember(const llvm::StringRef& pName,
123                                InputTree::iterator pLastPos,
124                                InputTree::Mover* pMove)
125 {
126   bool exist;
127   ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
128   if (!exist) {
129     ArchiveMember& ar = entry->value();
130     if (pLastPos == m_pInputTree->root())
131       ar.file = &m_ArchiveFile;
132     else
133       ar.file = *pLastPos;
134     ar.lastPos = pLastPos;
135     ar.move = pMove;
136   }
137   return !exist;
138 }
139 
140 /// hasArchiveMember - check if an archive file is included or not
hasArchiveMember(const llvm::StringRef & pName) const141 bool Archive::hasArchiveMember(const llvm::StringRef& pName) const
142 {
143   return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end());
144 }
145 
146 /// getArchiveMember - get a archive member
getArchiveMember(const llvm::StringRef & pName)147 Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName)
148 {
149   ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName);
150   if (it != m_ArchiveMemberMap.end())
151     return &(it.getEntry()->value());
152   return NULL;
153 }
154 
155 /// getSymbolTable - get the symtab
getSymbolTable()156 Archive::SymTabType& Archive::getSymbolTable()
157 {
158   return m_SymTab;
159 }
160 
161 /// getSymbolTable - get the symtab
getSymbolTable() const162 const Archive::SymTabType& Archive::getSymbolTable() const
163 {
164   return m_SymTab;
165 }
166 
167 /// setSymTabSize - set the memory size of symtab
setSymTabSize(size_t pSize)168 void Archive::setSymTabSize(size_t pSize)
169 {
170   m_SymTabSize = pSize;
171 }
172 
173 /// getSymTabSize - get the memory size of symtab
getSymTabSize() const174 size_t Archive::getSymTabSize() const
175 {
176   return m_SymTabSize;
177 }
178 
179 /// numOfSymbols - return the number of symbols in symtab
numOfSymbols() const180 size_t Archive::numOfSymbols() const
181 {
182   return m_SymTab.size();
183 }
184 
185 /// addSymbol - add a symtab entry to symtab
186 /// @param pName - symbol name
187 /// @param pFileOffset - file offset in symtab represents a object file
addSymbol(const char * pName,uint32_t pFileOffset,enum Archive::Symbol::Status pStatus)188 void Archive::addSymbol(const char* pName,
189                         uint32_t pFileOffset,
190                         enum Archive::Symbol::Status pStatus)
191 {
192   Symbol* entry = m_SymbolFactory.allocate();
193   new (entry) Symbol(pName, pFileOffset, pStatus);
194   m_SymTab.push_back(entry);
195 }
196 
197 /// getSymbolName - get the symbol name with the given index
getSymbolName(size_t pSymIdx) const198 const std::string& Archive::getSymbolName(size_t pSymIdx) const
199 {
200   assert(pSymIdx < numOfSymbols());
201   return m_SymTab[pSymIdx]->name;
202 }
203 
204 /// getObjFileOffset - get the file offset that represent a object file
getObjFileOffset(size_t pSymIdx) const205 uint32_t Archive::getObjFileOffset(size_t pSymIdx) const
206 {
207   assert(pSymIdx < numOfSymbols());
208   return m_SymTab[pSymIdx]->fileOffset;
209 }
210 
211 /// getSymbolStatus - get the status of a symbol
getSymbolStatus(size_t pSymIdx) const212 enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const
213 {
214   assert(pSymIdx < numOfSymbols());
215   return m_SymTab[pSymIdx]->status;
216 }
217 
218 /// setSymbolStatus - set the status of a symbol
setSymbolStatus(size_t pSymIdx,enum Archive::Symbol::Status pStatus)219 void Archive::setSymbolStatus(size_t pSymIdx,
220                               enum Archive::Symbol::Status pStatus)
221 {
222   assert(pSymIdx < numOfSymbols());
223   m_SymTab[pSymIdx]->status = pStatus;
224 }
225 
226 /// getStrTable - get the extended name table
getStrTable()227 std::string& Archive::getStrTable()
228 {
229   return m_StrTab;
230 }
231 
232 /// getStrTable - get the extended name table
getStrTable() const233 const std::string& Archive::getStrTable() const
234 {
235   return m_StrTab;
236 }
237 
238 /// hasStrTable()
hasStrTable() const239 bool Archive::hasStrTable() const
240 {
241   return (m_StrTab.size() > 0);
242 }
243 
244 /// getMemberFile - get the member file in an archive member
245 /// @param pArchiveFile - Input reference of the archive member
246 /// @param pIsThinAR    - denote the archive menber is a Thin Archive or not
247 /// @param pName        - the name of the member file we want to get
248 /// @param pPath        - the path of the member file
249 /// @param pFileOffset  - the file offset of the member file in a regular AR
250 /// FIXME: maybe we should not construct input file here
getMemberFile(Input & pArchiveFile,bool isThinAR,const std::string & pName,const sys::fs::Path & pPath,off_t pFileOffset)251 Input* Archive::getMemberFile(Input& pArchiveFile,
252                               bool isThinAR,
253                               const std::string& pName,
254                               const sys::fs::Path& pPath,
255                               off_t pFileOffset)
256 {
257   Input* member = NULL;
258   if (!isThinAR) {
259     member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset);
260     assert(member != NULL);
261     member->setMemArea(pArchiveFile.memArea());
262     m_Builder.setContext(*member);
263   }
264   else {
265     member = m_Builder.createInput(pName, pPath, Input::Unknown);
266     assert(member != NULL);
267     if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) {
268       error(diag::err_cannot_open_input) << member->name() << member->path();
269       return NULL;
270     }
271     m_Builder.setContext(*member);
272   }
273   return member;
274 }
275 
276