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 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 38 Archive::~Archive() 39 { 40 delete m_pInputTree; 41 } 42 43 /// getARFile - get the Input& of the archive file 44 Input& Archive::getARFile() 45 { 46 return m_ArchiveFile; 47 } 48 49 /// getARFile - get the Input& of the archive file 50 const Input& Archive::getARFile() const 51 { 52 return m_ArchiveFile; 53 } 54 55 /// inputs - get the input tree built from this archive 56 InputTree& Archive::inputs() 57 { 58 return *m_pInputTree; 59 } 60 61 /// inputs - get the input tree built from this archive 62 const InputTree& Archive::inputs() const 63 { 64 return *m_pInputTree; 65 } 66 67 /// getObjectMemberMap - get the map that contains the included object files 68 Archive::ObjectMemberMapType& Archive::getObjectMemberMap() 69 { 70 return m_ObjectMemberMap; 71 } 72 73 /// getObjectMemberMap - get the map that contains the included object files 74 const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const 75 { 76 return m_ObjectMemberMap; 77 } 78 79 /// numOfObjectMember - return the number of included object files 80 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 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 99 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 105 Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() 106 { 107 return m_ArchiveMemberMap; 108 } 109 110 /// getArchiveMemberMap - get the map that contains the included archive files 111 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 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 141 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 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 156 Archive::SymTabType& Archive::getSymbolTable() 157 { 158 return m_SymTab; 159 } 160 161 /// getSymbolTable - get the symtab 162 const Archive::SymTabType& Archive::getSymbolTable() const 163 { 164 return m_SymTab; 165 } 166 167 /// setSymTabSize - set the memory size of symtab 168 void Archive::setSymTabSize(size_t pSize) 169 { 170 m_SymTabSize = pSize; 171 } 172 173 /// getSymTabSize - get the memory size of symtab 174 size_t Archive::getSymTabSize() const 175 { 176 return m_SymTabSize; 177 } 178 179 /// numOfSymbols - return the number of symbols in symtab 180 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 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 198 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 205 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 212 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 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 227 std::string& Archive::getStrTable() 228 { 229 return m_StrTab; 230 } 231 232 /// getStrTable - get the extended name table 233 const std::string& Archive::getStrTable() const 234 { 235 return m_StrTab; 236 } 237 238 /// hasStrTable() 239 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 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