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