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