| //===- Archive.cpp --------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include <mcld/LD/Archive.h> |
| #include <mcld/MC/InputBuilder.h> |
| #include <mcld/MC/MCLDInput.h> |
| #include <mcld/MC/AttributeSet.h> |
| #include <mcld/MC/ContextFactory.h> |
| #include <llvm/ADT/StringRef.h> |
| #include <mcld/Support/MemoryAreaFactory.h> |
| #include <mcld/Support/MsgHandling.h> |
| |
| using namespace mcld; |
| |
| //===----------------------------------------------------------------------===// |
| // Archive |
| const char Archive::MAGIC[] = "!<arch>\n"; |
| const char Archive::THIN_MAGIC[] = "!<thin>\n"; |
| const size_t Archive::MAGIC_LEN = sizeof(Archive::MAGIC) - 1; |
| const char Archive::SVR4_SYMTAB_NAME[] = "/ "; |
| const char Archive::STRTAB_NAME[] = "// "; |
| const char Archive::PAD[] = "\n"; |
| const char Archive::MEMBER_MAGIC[] = "`\n"; |
| |
| Archive::Archive(Input& pInputFile, InputBuilder& pBuilder) |
| : m_ArchiveFile(pInputFile), |
| m_pInputTree(NULL), |
| m_SymbolFactory(32), |
| m_Builder(pBuilder) |
| { |
| // FIXME: move creation of input tree out of Archive. |
| m_pInputTree = new InputTree(); |
| } |
| |
| Archive::~Archive() |
| { |
| delete m_pInputTree; |
| } |
| |
| /// getARFile - get the Input& of the archive file |
| Input& Archive::getARFile() |
| { |
| return m_ArchiveFile; |
| } |
| |
| /// getARFile - get the Input& of the archive file |
| const Input& Archive::getARFile() const |
| { |
| return m_ArchiveFile; |
| } |
| |
| /// inputs - get the input tree built from this archive |
| InputTree& Archive::inputs() |
| { |
| return *m_pInputTree; |
| } |
| |
| /// inputs - get the input tree built from this archive |
| const InputTree& Archive::inputs() const |
| { |
| return *m_pInputTree; |
| } |
| |
| /// getObjectMemberMap - get the map that contains the included object files |
| Archive::ObjectMemberMapType& Archive::getObjectMemberMap() |
| { |
| return m_ObjectMemberMap; |
| } |
| |
| /// getObjectMemberMap - get the map that contains the included object files |
| const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const |
| { |
| return m_ObjectMemberMap; |
| } |
| |
| /// numOfObjectMember - return the number of included object files |
| size_t Archive::numOfObjectMember() const |
| { |
| return m_ObjectMemberMap.numOfEntries(); |
| } |
| |
| /// addObjectMember - add a object in the object member map |
| /// @param pFileOffset - file offset in symtab represents a object file |
| /// @param pIter - the iterator in the input tree built from this archive |
| bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter) |
| { |
| bool exist; |
| ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist); |
| if (!exist) |
| entry->setValue(pIter); |
| return !exist; |
| } |
| |
| /// hasObjectMember - check if a object file is included or not |
| /// @param pFileOffset - file offset in symtab represents a object file |
| bool Archive::hasObjectMember(uint32_t pFileOffset) const |
| { |
| return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end()); |
| } |
| |
| /// getArchiveMemberMap - get the map that contains the included archive files |
| Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() |
| { |
| return m_ArchiveMemberMap; |
| } |
| |
| /// getArchiveMemberMap - get the map that contains the included archive files |
| const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const |
| { |
| return m_ArchiveMemberMap; |
| } |
| |
| /// addArchiveMember - add an archive in the archive member map |
| /// @param pName - the name of the new archive member |
| /// @param pLastPos - this records the point to insert the next node in the |
| /// subtree of this archive member |
| /// @param pMove - this records the direction to insert the next node in the |
| /// subtree of this archive member |
| bool Archive::addArchiveMember(const llvm::StringRef& pName, |
| InputTree::iterator pLastPos, |
| InputTree::Mover* pMove) |
| { |
| bool exist; |
| ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist); |
| if (!exist) { |
| ArchiveMember& ar = entry->value(); |
| ar.file = *pLastPos; |
| ar.lastPos = pLastPos; |
| ar.move = pMove; |
| } |
| return !exist; |
| } |
| |
| /// hasArchiveMember - check if an archive file is included or not |
| bool Archive::hasArchiveMember(const llvm::StringRef& pName) const |
| { |
| return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end()); |
| } |
| |
| /// getArchiveMember - get a archive member |
| Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName) |
| { |
| ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName); |
| if (it != m_ArchiveMemberMap.end()) |
| return &(it.getEntry()->value()); |
| return NULL; |
| } |
| |
| /// getSymbolTable - get the symtab |
| Archive::SymTabType& Archive::getSymbolTable() |
| { |
| return m_SymTab; |
| } |
| |
| /// getSymbolTable - get the symtab |
| const Archive::SymTabType& Archive::getSymbolTable() const |
| { |
| return m_SymTab; |
| } |
| |
| /// setSymTabSize - set the memory size of symtab |
| void Archive::setSymTabSize(size_t pSize) |
| { |
| m_SymTabSize = pSize; |
| } |
| |
| /// getSymTabSize - get the memory size of symtab |
| size_t Archive::getSymTabSize() const |
| { |
| return m_SymTabSize; |
| } |
| |
| /// numOfSymbols - return the number of symbols in symtab |
| size_t Archive::numOfSymbols() const |
| { |
| return m_SymTab.size(); |
| } |
| |
| /// addSymbol - add a symtab entry to symtab |
| /// @param pName - symbol name |
| /// @param pFileOffset - file offset in symtab represents a object file |
| void Archive::addSymbol(const char* pName, |
| uint32_t pFileOffset, |
| enum Archive::Symbol::Status pStatus) |
| { |
| Symbol* entry = m_SymbolFactory.allocate(); |
| new (entry) Symbol(pName, pFileOffset, pStatus); |
| m_SymTab.push_back(entry); |
| } |
| |
| /// getSymbolName - get the symbol name with the given index |
| const std::string& Archive::getSymbolName(size_t pSymIdx) const |
| { |
| assert(pSymIdx < numOfSymbols()); |
| return m_SymTab[pSymIdx]->name; |
| } |
| |
| /// getObjFileOffset - get the file offset that represent a object file |
| uint32_t Archive::getObjFileOffset(size_t pSymIdx) const |
| { |
| assert(pSymIdx < numOfSymbols()); |
| return m_SymTab[pSymIdx]->fileOffset; |
| } |
| |
| /// getSymbolStatus - get the status of a symbol |
| enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const |
| { |
| assert(pSymIdx < numOfSymbols()); |
| return m_SymTab[pSymIdx]->status; |
| } |
| |
| /// setSymbolStatus - set the status of a symbol |
| void Archive::setSymbolStatus(size_t pSymIdx, |
| enum Archive::Symbol::Status pStatus) |
| { |
| assert(pSymIdx < numOfSymbols()); |
| m_SymTab[pSymIdx]->status = pStatus; |
| } |
| |
| /// getStrTable - get the extended name table |
| std::string& Archive::getStrTable() |
| { |
| return m_StrTab; |
| } |
| |
| /// getStrTable - get the extended name table |
| const std::string& Archive::getStrTable() const |
| { |
| return m_StrTab; |
| } |
| |
| /// hasStrTable() |
| bool Archive::hasStrTable() const |
| { |
| return (m_StrTab.size() > 0); |
| } |
| |
| /// getMemberFile - get the member file in an archive member |
| /// @param pArchiveFile - Input reference of the archive member |
| /// @param pIsThinAR - denote the archive menber is a Thin Archive or not |
| /// @param pName - the name of the member file we want to get |
| /// @param pPath - the path of the member file |
| /// @param pFileOffset - the file offset of the member file in a regular AR |
| /// FIXME: maybe we should not construct input file here |
| Input* Archive::getMemberFile(Input& pArchiveFile, |
| bool isThinAR, |
| const std::string& pName, |
| const sys::fs::Path& pPath, |
| off_t pFileOffset) |
| { |
| Input* member = NULL; |
| if (!isThinAR) { |
| member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset); |
| assert(member != NULL); |
| member->setMemArea(pArchiveFile.memArea()); |
| m_Builder.setContext(*member); |
| } |
| else { |
| member = m_Builder.createInput(pName, pPath, Input::Unknown); |
| assert(member != NULL); |
| if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) { |
| error(diag::err_cannot_open_input) << member->name() << member->path(); |
| return NULL; |
| } |
| m_Builder.setContext(*member); |
| } |
| return member; |
| } |
| |