Archive.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 18using namespace mcld; 19 20//===----------------------------------------------------------------------===// 21// Archive 22const char Archive::MAGIC[] = "!<arch>\n"; 23const char Archive::THIN_MAGIC[] = "!<thin>\n"; 24const size_t Archive::MAGIC_LEN = sizeof(Archive::MAGIC) - 1; 25const char Archive::SVR4_SYMTAB_NAME[] = "/ "; 26const char Archive::STRTAB_NAME[] = "// "; 27const char Archive::PAD[] = "\n"; 28const char Archive::MEMBER_MAGIC[] = "`\n"; 29 30Archive::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 40Archive::~Archive() 41{ 42 delete m_pInputTree; 43} 44 45/// getARFile - get the Input& of the archive file 46Input& Archive::getARFile() 47{ 48 return m_ArchiveFile; 49} 50 51/// getARFile - get the Input& of the archive file 52const Input& Archive::getARFile() const 53{ 54 return m_ArchiveFile; 55} 56 57/// inputs - get the input tree built from this archive 58InputTree& Archive::inputs() 59{ 60 return *m_pInputTree; 61} 62 63/// inputs - get the input tree built from this archive 64const InputTree& Archive::inputs() const 65{ 66 return *m_pInputTree; 67} 68 69/// getObjectMemberMap - get the map that contains the included object files 70Archive::ObjectMemberMapType& Archive::getObjectMemberMap() 71{ 72 return m_ObjectMemberMap; 73} 74 75/// getObjectMemberMap - get the map that contains the included object files 76const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const 77{ 78 return m_ObjectMemberMap; 79} 80 81/// numOfObjectMember - return the number of included object files 82size_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 90bool 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 101bool 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 107Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() 108{ 109 return m_ArchiveMemberMap; 110} 111 112/// getArchiveMemberMap - get the map that contains the included archive files 113const 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 124bool 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 ar.file = *pLastPos; 133 ar.lastPos = pLastPos; 134 ar.move = pMove; 135 } 136 return !exist; 137} 138 139/// hasArchiveMember - check if an archive file is included or not 140bool Archive::hasArchiveMember(const llvm::StringRef& pName) const 141{ 142 return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end()); 143} 144 145/// getArchiveMember - get a archive member 146Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName) 147{ 148 ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName); 149 if (it != m_ArchiveMemberMap.end()) 150 return &(it.getEntry()->value()); 151 return NULL; 152} 153 154/// getSymbolTable - get the symtab 155Archive::SymTabType& Archive::getSymbolTable() 156{ 157 return m_SymTab; 158} 159 160/// getSymbolTable - get the symtab 161const Archive::SymTabType& Archive::getSymbolTable() const 162{ 163 return m_SymTab; 164} 165 166/// setSymTabSize - set the memory size of symtab 167void Archive::setSymTabSize(size_t pSize) 168{ 169 m_SymTabSize = pSize; 170} 171 172/// getSymTabSize - get the memory size of symtab 173size_t Archive::getSymTabSize() const 174{ 175 return m_SymTabSize; 176} 177 178/// numOfSymbols - return the number of symbols in symtab 179size_t Archive::numOfSymbols() const 180{ 181 return m_SymTab.size(); 182} 183 184/// addSymbol - add a symtab entry to symtab 185/// @param pName - symbol name 186/// @param pFileOffset - file offset in symtab represents a object file 187void Archive::addSymbol(const char* pName, 188 uint32_t pFileOffset, 189 enum Archive::Symbol::Status pStatus) 190{ 191 Symbol* entry = m_SymbolFactory.allocate(); 192 new (entry) Symbol(pName, pFileOffset, pStatus); 193 m_SymTab.push_back(entry); 194} 195 196/// getSymbolName - get the symbol name with the given index 197const std::string& Archive::getSymbolName(size_t pSymIdx) const 198{ 199 assert(pSymIdx < numOfSymbols()); 200 return m_SymTab[pSymIdx]->name; 201} 202 203/// getObjFileOffset - get the file offset that represent a object file 204uint32_t Archive::getObjFileOffset(size_t pSymIdx) const 205{ 206 assert(pSymIdx < numOfSymbols()); 207 return m_SymTab[pSymIdx]->fileOffset; 208} 209 210/// getSymbolStatus - get the status of a symbol 211enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const 212{ 213 assert(pSymIdx < numOfSymbols()); 214 return m_SymTab[pSymIdx]->status; 215} 216 217/// setSymbolStatus - set the status of a symbol 218void Archive::setSymbolStatus(size_t pSymIdx, 219 enum Archive::Symbol::Status pStatus) 220{ 221 assert(pSymIdx < numOfSymbols()); 222 m_SymTab[pSymIdx]->status = pStatus; 223} 224 225/// getStrTable - get the extended name table 226std::string& Archive::getStrTable() 227{ 228 return m_StrTab; 229} 230 231/// getStrTable - get the extended name table 232const std::string& Archive::getStrTable() const 233{ 234 return m_StrTab; 235} 236 237/// hasStrTable() 238bool Archive::hasStrTable() const 239{ 240 return (m_StrTab.size() > 0); 241} 242 243/// getMemberFile - get the member file in an archive member 244/// @param pArchiveFile - Input reference of the archive member 245/// @param pIsThinAR - denote the archive menber is a Thin Archive or not 246/// @param pName - the name of the member file we want to get 247/// @param pPath - the path of the member file 248/// @param pFileOffset - the file offset of the member file in a regular AR 249/// FIXME: maybe we should not construct input file here 250Input* Archive::getMemberFile(Input& pArchiveFile, 251 bool isThinAR, 252 const std::string& pName, 253 const sys::fs::Path& pPath, 254 off_t pFileOffset) 255{ 256 Input* member = NULL; 257 if (!isThinAR) { 258 member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset); 259 assert(member != NULL); 260 member->setMemArea(pArchiveFile.memArea()); 261 m_Builder.setContext(*member); 262 } 263 else { 264 member = m_Builder.createInput(pName, pPath, Input::Unknown); 265 assert(member != NULL); 266 if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) { 267 error(diag::err_cannot_open_input) << member->name() << member->path(); 268 return NULL; 269 } 270 m_Builder.setContext(*member); 271 } 272 return member; 273} 274 275