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