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