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