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/InputBuilder.h>
     11 #include <mcld/MC/Input.h>
     12 #include <llvm/ADT/StringRef.h>
     13 #include <mcld/Support/MsgHandling.h>
     14 
     15 using namespace mcld;
     16 
     17 //===----------------------------------------------------------------------===//
     18 // Archive
     19 const char   Archive::MAGIC[]            = "!<arch>\n";
     20 const char   Archive::THIN_MAGIC[]       = "!<thin>\n";
     21 const size_t Archive::MAGIC_LEN          = sizeof(Archive::MAGIC) - 1;
     22 const char   Archive::SVR4_SYMTAB_NAME[] = "/               ";
     23 const char   Archive::IRIX6_SYMTAB_NAME[]= "/SYM64/         ";
     24 const char   Archive::STRTAB_NAME[]      = "//              ";
     25 const char   Archive::PAD[]              = "\n";
     26 const char   Archive::MEMBER_MAGIC[]     = "`\n";
     27 
     28 Archive::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 
     38 Archive::~Archive()
     39 {
     40   delete m_pInputTree;
     41 }
     42 
     43 /// getARFile - get the Input& of the archive file
     44 Input& Archive::getARFile()
     45 {
     46   return m_ArchiveFile;
     47 }
     48 
     49 /// getARFile - get the Input& of the archive file
     50 const Input& Archive::getARFile() const
     51 {
     52   return m_ArchiveFile;
     53 }
     54 
     55 /// inputs - get the input tree built from this archive
     56 InputTree& Archive::inputs()
     57 {
     58   return *m_pInputTree;
     59 }
     60 
     61 /// inputs - get the input tree built from this archive
     62 const InputTree& Archive::inputs() const
     63 {
     64   return *m_pInputTree;
     65 }
     66 
     67 /// getObjectMemberMap - get the map that contains the included object files
     68 Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
     69 {
     70   return m_ObjectMemberMap;
     71 }
     72 
     73 /// getObjectMemberMap - get the map that contains the included object files
     74 const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
     75 {
     76   return m_ObjectMemberMap;
     77 }
     78 
     79 /// numOfObjectMember - return the number of included object files
     80 size_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
     88 bool 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
     99 bool 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
    105 Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
    106 {
    107   return m_ArchiveMemberMap;
    108 }
    109 
    110 /// getArchiveMemberMap - get the map that contains the included archive files
    111 const 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
    122 bool 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
    141 bool 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
    147 Archive::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
    156 Archive::SymTabType& Archive::getSymbolTable()
    157 {
    158   return m_SymTab;
    159 }
    160 
    161 /// getSymbolTable - get the symtab
    162 const Archive::SymTabType& Archive::getSymbolTable() const
    163 {
    164   return m_SymTab;
    165 }
    166 
    167 /// setSymTabSize - set the memory size of symtab
    168 void Archive::setSymTabSize(size_t pSize)
    169 {
    170   m_SymTabSize = pSize;
    171 }
    172 
    173 /// getSymTabSize - get the memory size of symtab
    174 size_t Archive::getSymTabSize() const
    175 {
    176   return m_SymTabSize;
    177 }
    178 
    179 /// numOfSymbols - return the number of symbols in symtab
    180 size_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
    188 void 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
    198 const 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
    205 uint32_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
    212 enum 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
    219 void 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
    227 std::string& Archive::getStrTable()
    228 {
    229   return m_StrTab;
    230 }
    231 
    232 /// getStrTable - get the extended name table
    233 const std::string& Archive::getStrTable() const
    234 {
    235   return m_StrTab;
    236 }
    237 
    238 /// hasStrTable()
    239 bool 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
    251 Input* 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