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 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 38 Archive::~Archive() { 39 delete m_pInputTree; 40 } 41 42 /// getARFile - get the Input& of the archive file 43 Input& Archive::getARFile() { 44 return m_ArchiveFile; 45 } 46 47 /// getARFile - get the Input& of the archive file 48 const Input& Archive::getARFile() const { 49 return m_ArchiveFile; 50 } 51 52 /// inputs - get the input tree built from this archive 53 InputTree& Archive::inputs() { 54 return *m_pInputTree; 55 } 56 57 /// inputs - get the input tree built from this archive 58 const InputTree& Archive::inputs() const { 59 return *m_pInputTree; 60 } 61 62 /// getObjectMemberMap - get the map that contains the included object files 63 Archive::ObjectMemberMapType& Archive::getObjectMemberMap() { 64 return m_ObjectMemberMap; 65 } 66 67 /// getObjectMemberMap - get the map that contains the included object files 68 const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const { 69 return m_ObjectMemberMap; 70 } 71 72 /// numOfObjectMember - return the number of included object files 73 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 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 90 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 95 Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() { 96 return m_ArchiveMemberMap; 97 } 98 99 /// getArchiveMemberMap - get the map that contains the included archive files 100 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 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 128 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 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 142 Archive::SymTabType& Archive::getSymbolTable() { 143 return m_SymTab; 144 } 145 146 /// getSymbolTable - get the symtab 147 const Archive::SymTabType& Archive::getSymbolTable() const { 148 return m_SymTab; 149 } 150 151 /// setSymTabSize - set the memory size of symtab 152 void Archive::setSymTabSize(size_t pSize) { 153 m_SymTabSize = pSize; 154 } 155 156 /// getSymTabSize - get the memory size of symtab 157 size_t Archive::getSymTabSize() const { 158 return m_SymTabSize; 159 } 160 161 /// numOfSymbols - return the number of symbols in symtab 162 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 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 178 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 184 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 190 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 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 203 std::string& Archive::getStrTable() { 204 return m_StrTab; 205 } 206 207 /// getStrTable - get the extended name table 208 const std::string& Archive::getStrTable() const { 209 return m_StrTab; 210 } 211 212 /// hasStrTable() 213 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 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