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 16namespace mcld { 17 18//===----------------------------------------------------------------------===// 19// Archive 20const char Archive::MAGIC[] = "!<arch>\n"; 21const char Archive::THIN_MAGIC[] = "!<thin>\n"; 22const size_t Archive::MAGIC_LEN = sizeof(Archive::MAGIC) - 1; 23const char Archive::SVR4_SYMTAB_NAME[] = "/ "; 24const char Archive::IRIX6_SYMTAB_NAME[] = "/SYM64/ "; 25const char Archive::STRTAB_NAME[] = "// "; 26const char Archive::PAD[] = "\n"; 27const char Archive::MEMBER_MAGIC[] = "`\n"; 28 29Archive::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 38Archive::~Archive() { 39 delete m_pInputTree; 40} 41 42/// getARFile - get the Input& of the archive file 43Input& Archive::getARFile() { 44 return m_ArchiveFile; 45} 46 47/// getARFile - get the Input& of the archive file 48const Input& Archive::getARFile() const { 49 return m_ArchiveFile; 50} 51 52/// inputs - get the input tree built from this archive 53InputTree& Archive::inputs() { 54 return *m_pInputTree; 55} 56 57/// inputs - get the input tree built from this archive 58const InputTree& Archive::inputs() const { 59 return *m_pInputTree; 60} 61 62/// getObjectMemberMap - get the map that contains the included object files 63Archive::ObjectMemberMapType& Archive::getObjectMemberMap() { 64 return m_ObjectMemberMap; 65} 66 67/// getObjectMemberMap - get the map that contains the included object files 68const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const { 69 return m_ObjectMemberMap; 70} 71 72/// numOfObjectMember - return the number of included object files 73size_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 80bool 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 90bool 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 95Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() { 96 return m_ArchiveMemberMap; 97} 98 99/// getArchiveMemberMap - get the map that contains the included archive files 100const 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 110bool 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 128bool Archive::hasArchiveMember(const llvm::StringRef& pName) const { 129 return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end()); 130} 131 132/// getArchiveMember - get a archive member 133Archive::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 142Archive::SymTabType& Archive::getSymbolTable() { 143 return m_SymTab; 144} 145 146/// getSymbolTable - get the symtab 147const Archive::SymTabType& Archive::getSymbolTable() const { 148 return m_SymTab; 149} 150 151/// setSymTabSize - set the memory size of symtab 152void Archive::setSymTabSize(size_t pSize) { 153 m_SymTabSize = pSize; 154} 155 156/// getSymTabSize - get the memory size of symtab 157size_t Archive::getSymTabSize() const { 158 return m_SymTabSize; 159} 160 161/// numOfSymbols - return the number of symbols in symtab 162size_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 169void 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 178const 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 184uint32_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 190enum 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 196void 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 203std::string& Archive::getStrTable() { 204 return m_StrTab; 205} 206 207/// getStrTable - get the extended name table 208const std::string& Archive::getStrTable() const { 209 return m_StrTab; 210} 211 212/// hasStrTable() 213bool 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 224Input* 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