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/InputFactory.h>
11 #include <llvm/ADT/StringRef.h>
12
13 using namespace mcld;
14
15 //===----------------------------------------------------------------------===//
16 // Archive
17 const char Archive::MAGIC[] = "!<arch>\n";
18 const char Archive::THIN_MAGIC[] = "!<thin>\n";
19 const size_t Archive::MAGIC_LEN = sizeof(Archive::MAGIC) - 1;
20 const char Archive::SVR4_SYMTAB_NAME[] = "/ ";
21 const char Archive::STRTAB_NAME[] = "// ";
22 const char Archive::PAD[] = "\n";
23 const char Archive::MEMBER_MAGIC[] = "`\n";
24
Archive(Input & pInputFile,InputFactory & pInputFactory)25 Archive::Archive(Input& pInputFile, InputFactory& pInputFactory)
26 : m_ArchiveFile(pInputFile),
27 m_pInputTree(NULL),
28 m_SymbolFactory(32)
29 {
30 m_pInputTree = new InputTree(pInputFactory);
31 }
32
~Archive()33 Archive::~Archive()
34 {
35 delete m_pInputTree;
36 }
37
38 /// getARFile - get the Input& of the archive file
getARFile()39 Input& Archive::getARFile()
40 {
41 return m_ArchiveFile;
42 }
43
44 /// getARFile - get the Input& of the archive file
getARFile() const45 const Input& Archive::getARFile() const
46 {
47 return m_ArchiveFile;
48 }
49
50 /// inputs - get the input tree built from this archive
inputs()51 InputTree& Archive::inputs()
52 {
53 return *m_pInputTree;
54 }
55
56 /// inputs - get the input tree built from this archive
inputs() const57 const InputTree& Archive::inputs() const
58 {
59 return *m_pInputTree;
60 }
61
62 /// getObjectMemberMap - get the map that contains the included object files
getObjectMemberMap()63 Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
64 {
65 return m_ObjectMemberMap;
66 }
67
68 /// getObjectMemberMap - get the map that contains the included object files
getObjectMemberMap() const69 const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
70 {
71 return m_ObjectMemberMap;
72 }
73
74 /// numOfObjectMember - return the number of included object files
numOfObjectMember() const75 size_t Archive::numOfObjectMember() const
76 {
77 return m_ObjectMemberMap.numOfEntries();
78 }
79
80 /// addObjectMember - add a object in the object member map
81 /// @param pFileOffset - file offset in symtab represents a object file
82 /// @param pIter - the iterator in the input tree built from this archive
addObjectMember(uint32_t pFileOffset,InputTree::iterator pIter)83 bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter)
84 {
85 bool exist;
86 ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist);
87 if (!exist)
88 entry->setValue(pIter);
89 return !exist;
90 }
91
92 /// hasObjectMember - check if a object file is included or not
93 /// @param pFileOffset - file offset in symtab represents a object file
hasObjectMember(uint32_t pFileOffset) const94 bool Archive::hasObjectMember(uint32_t pFileOffset) const
95 {
96 return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end());
97 }
98
99 /// getArchiveMemberMap - get the map that contains the included archive files
getArchiveMemberMap()100 Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
101 {
102 return m_ArchiveMemberMap;
103 }
104
105 /// getArchiveMemberMap - get the map that contains the included archive files
getArchiveMemberMap() const106 const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const
107 {
108 return m_ArchiveMemberMap;
109 }
110
111 /// addArchiveMember - add an archive in the archive member map
112 /// @param pName - the name of the new archive member
113 /// @param pLastPos - this records the point to insert the next node in the
114 /// subtree of this archive member
115 /// @param pMove - this records the direction to insert the next node in the
116 /// subtree of this archive member
addArchiveMember(const llvm::StringRef & pName,InputTree::iterator pLastPos,InputTree::Mover * pMove)117 bool Archive::addArchiveMember(const llvm::StringRef& pName,
118 InputTree::iterator pLastPos,
119 InputTree::Mover* pMove)
120 {
121 bool exist;
122 ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
123 if (!exist) {
124 ArchiveMember& ar = entry->value();
125 ar.file = *pLastPos;
126 ar.lastPos = pLastPos;
127 ar.move = pMove;
128 }
129 return !exist;
130 }
131
132 /// hasArchiveMember - check if an archive file is included or not
hasArchiveMember(const llvm::StringRef & pName) const133 bool Archive::hasArchiveMember(const llvm::StringRef& pName) const
134 {
135 return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end());
136 }
137
138 /// getArchiveMember - get a archive member
getArchiveMember(const llvm::StringRef & pName)139 Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName)
140 {
141 ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName);
142 if (it != m_ArchiveMemberMap.end())
143 return &(it.getEntry()->value());
144 return NULL;
145 }
146
147 /// getSymbolTable - get the symtab
getSymbolTable()148 Archive::SymTabType& Archive::getSymbolTable()
149 {
150 return m_SymTab;
151 }
152
153 /// getSymbolTable - get the symtab
getSymbolTable() const154 const Archive::SymTabType& Archive::getSymbolTable() const
155 {
156 return m_SymTab;
157 }
158
159 /// setSymTabSize - set the memory size of symtab
setSymTabSize(size_t pSize)160 void Archive::setSymTabSize(size_t pSize)
161 {
162 m_SymTabSize = pSize;
163 }
164
165 /// getSymTabSize - get the memory size of symtab
getSymTabSize() const166 size_t Archive::getSymTabSize() const
167 {
168 return m_SymTabSize;
169 }
170
171 /// numOfSymbols - return the number of symbols in symtab
numOfSymbols() const172 size_t Archive::numOfSymbols() const
173 {
174 return m_SymTab.size();
175 }
176
177 /// addSymbol - add a symtab entry to symtab
178 /// @param pName - symbol name
179 /// @param pFileOffset - file offset in symtab represents a object file
addSymbol(const char * pName,uint32_t pFileOffset,enum Archive::Symbol::Status pStatus)180 void Archive::addSymbol(const char* pName,
181 uint32_t pFileOffset,
182 enum Archive::Symbol::Status pStatus)
183 {
184 Symbol* entry = m_SymbolFactory.allocate();
185 new (entry) Symbol(pName, pFileOffset, pStatus);
186 m_SymTab.push_back(entry);
187 }
188
189 /// getSymbolName - get the symbol name with the given index
getSymbolName(size_t pSymIdx) const190 const std::string& Archive::getSymbolName(size_t pSymIdx) const
191 {
192 assert(pSymIdx < numOfSymbols());
193 return m_SymTab[pSymIdx]->name;
194 }
195
196 /// getObjFileOffset - get the file offset that represent a object file
getObjFileOffset(size_t pSymIdx) const197 uint32_t Archive::getObjFileOffset(size_t pSymIdx) const
198 {
199 assert(pSymIdx < numOfSymbols());
200 return m_SymTab[pSymIdx]->fileOffset;
201 }
202
203 /// getSymbolStatus - get the status of a symbol
getSymbolStatus(size_t pSymIdx) const204 enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const
205 {
206 assert(pSymIdx < numOfSymbols());
207 return m_SymTab[pSymIdx]->status;
208 }
209
210 /// setSymbolStatus - set the status of a symbol
setSymbolStatus(size_t pSymIdx,enum Archive::Symbol::Status pStatus)211 void Archive::setSymbolStatus(size_t pSymIdx,
212 enum Archive::Symbol::Status pStatus)
213 {
214 assert(pSymIdx < numOfSymbols());
215 m_SymTab[pSymIdx]->status = pStatus;
216 }
217
218 /// getStrTable - get the extended name table
getStrTable()219 std::string& Archive::getStrTable()
220 {
221 return m_StrTab;
222 }
223
224 /// getStrTable - get the extended name table
getStrTable() const225 const std::string& Archive::getStrTable() const
226 {
227 return m_StrTab;
228 }
229
230