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