Home | History | Annotate | Download | only in Archive
      1 //===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the implementation of the Archive and ArchiveMember
     11 // classes that is common to both reading and writing archives..
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "ArchiveInternals.h"
     16 #include "llvm/Bitcode/ReaderWriter.h"
     17 #include "llvm/Module.h"
     18 #include "llvm/Support/FileSystem.h"
     19 #include "llvm/Support/MemoryBuffer.h"
     20 #include "llvm/Support/Process.h"
     21 #include "llvm/Support/system_error.h"
     22 #include <memory>
     23 #include <cstring>
     24 using namespace llvm;
     25 
     26 // getMemberSize - compute the actual physical size of the file member as seen
     27 // on disk. This isn't the size of member's payload. Use getSize() for that.
     28 unsigned
     29 ArchiveMember::getMemberSize() const {
     30   // Basically its the file size plus the header size
     31   unsigned result =  info.fileSize + sizeof(ArchiveMemberHeader);
     32 
     33   // If it has a long filename, include the name length
     34   if (hasLongFilename())
     35     result += path.str().length() + 1;
     36 
     37   // If its now odd lengthed, include the padding byte
     38   if (result % 2 != 0 )
     39     result++;
     40 
     41   return result;
     42 }
     43 
     44 // This default constructor is only use by the ilist when it creates its
     45 // sentry node. We give it specific static values to make it stand out a bit.
     46 ArchiveMember::ArchiveMember()
     47   : parent(0), path("--invalid--"), flags(0), data(0)
     48 {
     49   info.user = sys::Process::GetCurrentUserId();
     50   info.group = sys::Process::GetCurrentGroupId();
     51   info.mode = 0777;
     52   info.fileSize = 0;
     53   info.modTime = sys::TimeValue::now();
     54 }
     55 
     56 // This is the constructor that the Archive class uses when it is building or
     57 // reading an archive. It just defaults a few things and ensures the parent is
     58 // set for the iplist. The Archive class fills in the ArchiveMember's data.
     59 // This is required because correctly setting the data may depend on other
     60 // things in the Archive.
     61 ArchiveMember::ArchiveMember(Archive* PAR)
     62   : parent(PAR), path(), flags(0), data(0)
     63 {
     64 }
     65 
     66 // This method allows an ArchiveMember to be replaced with the data for a
     67 // different file, presumably as an update to the member. It also makes sure
     68 // the flags are reset correctly.
     69 bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
     70   bool Exists;
     71   if (sys::fs::exists(newFile.str(), Exists) || !Exists) {
     72     if (ErrMsg)
     73       *ErrMsg = "Can not replace an archive member with a non-existent file";
     74     return true;
     75   }
     76 
     77   data = 0;
     78   path = newFile;
     79 
     80   // SVR4 symbol tables have an empty name
     81   if (path.str() == ARFILE_SVR4_SYMTAB_NAME)
     82     flags |= SVR4SymbolTableFlag;
     83   else
     84     flags &= ~SVR4SymbolTableFlag;
     85 
     86   // BSD4.4 symbol tables have a special name
     87   if (path.str() == ARFILE_BSD4_SYMTAB_NAME)
     88     flags |= BSD4SymbolTableFlag;
     89   else
     90     flags &= ~BSD4SymbolTableFlag;
     91 
     92   // LLVM symbol tables have a very specific name
     93   if (path.str() == ARFILE_LLVM_SYMTAB_NAME)
     94     flags |= LLVMSymbolTableFlag;
     95   else
     96     flags &= ~LLVMSymbolTableFlag;
     97 
     98   // String table name
     99   if (path.str() == ARFILE_STRTAB_NAME)
    100     flags |= StringTableFlag;
    101   else
    102     flags &= ~StringTableFlag;
    103 
    104   // If it has a slash then it has a path
    105   bool hasSlash = path.str().find('/') != std::string::npos;
    106   if (hasSlash)
    107     flags |= HasPathFlag;
    108   else
    109     flags &= ~HasPathFlag;
    110 
    111   // If it has a slash or its over 15 chars then its a long filename format
    112   if (hasSlash || path.str().length() > 15)
    113     flags |= HasLongFilenameFlag;
    114   else
    115     flags &= ~HasLongFilenameFlag;
    116 
    117   // Get the signature and status info
    118   const char* signature = (const char*) data;
    119   SmallString<4> magic;
    120   if (!signature) {
    121     sys::fs::get_magic(path.str(), magic.capacity(), magic);
    122     signature = magic.c_str();
    123     const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg);
    124     if (FSinfo)
    125       info = *FSinfo;
    126     else
    127       return true;
    128   }
    129 
    130   // Determine what kind of file it is.
    131   switch (sys::IdentifyFileType(signature,4)) {
    132     case sys::Bitcode_FileType:
    133       flags |= BitcodeFlag;
    134       break;
    135     default:
    136       flags &= ~BitcodeFlag;
    137       break;
    138   }
    139   return false;
    140 }
    141 
    142 // Archive constructor - this is the only constructor that gets used for the
    143 // Archive class. Everything else (default,copy) is deprecated. This just
    144 // initializes and maps the file into memory, if requested.
    145 Archive::Archive(const sys::Path& filename, LLVMContext& C)
    146   : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
    147     symTabSize(0), firstFileOffset(0), modules(), foreignST(0), Context(C) {
    148 }
    149 
    150 bool
    151 Archive::mapToMemory(std::string* ErrMsg) {
    152   OwningPtr<MemoryBuffer> File;
    153   if (error_code ec = MemoryBuffer::getFile(archPath.c_str(), File)) {
    154     if (ErrMsg)
    155       *ErrMsg = ec.message();
    156     return true;
    157   }
    158   mapfile = File.take();
    159   base = mapfile->getBufferStart();
    160   return false;
    161 }
    162 
    163 void Archive::cleanUpMemory() {
    164   // Shutdown the file mapping
    165   delete mapfile;
    166   mapfile = 0;
    167   base = 0;
    168 
    169   // Forget the entire symbol table
    170   symTab.clear();
    171   symTabSize = 0;
    172 
    173   firstFileOffset = 0;
    174 
    175   // Free the foreign symbol table member
    176   if (foreignST) {
    177     delete foreignST;
    178     foreignST = 0;
    179   }
    180 
    181   // Delete any Modules and ArchiveMember's we've allocated as a result of
    182   // symbol table searches.
    183   for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) {
    184     delete I->second.first;
    185     delete I->second.second;
    186   }
    187 }
    188 
    189 // Archive destructor - just clean up memory
    190 Archive::~Archive() {
    191   cleanUpMemory();
    192 }
    193 
    194 
    195 
    196 static void getSymbols(Module*M, std::vector<std::string>& symbols) {
    197   // Loop over global variables
    198   for (Module::global_iterator GI = M->global_begin(), GE=M->global_end(); GI != GE; ++GI)
    199     if (!GI->isDeclaration() && !GI->hasLocalLinkage())
    200       if (!GI->getName().empty())
    201         symbols.push_back(GI->getName());
    202 
    203   // Loop over functions
    204   for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI)
    205     if (!FI->isDeclaration() && !FI->hasLocalLinkage())
    206       if (!FI->getName().empty())
    207         symbols.push_back(FI->getName());
    208 
    209   // Loop over aliases
    210   for (Module::alias_iterator AI = M->alias_begin(), AE = M->alias_end();
    211        AI != AE; ++AI) {
    212     if (AI->hasName())
    213       symbols.push_back(AI->getName());
    214   }
    215 }
    216 
    217 // Get just the externally visible defined symbols from the bitcode
    218 bool llvm::GetBitcodeSymbols(const sys::Path& fName,
    219                              LLVMContext& Context,
    220                              std::vector<std::string>& symbols,
    221                              std::string* ErrMsg) {
    222   OwningPtr<MemoryBuffer> Buffer;
    223   if (error_code ec = MemoryBuffer::getFileOrSTDIN(fName.c_str(), Buffer)) {
    224     if (ErrMsg) *ErrMsg = "Could not open file '" + fName.str() + "'" + ": "
    225                         + ec.message();
    226     return true;
    227   }
    228 
    229   Module *M = ParseBitcodeFile(Buffer.get(), Context, ErrMsg);
    230   if (!M)
    231     return true;
    232 
    233   // Get the symbols
    234   getSymbols(M, symbols);
    235 
    236   // Done with the module.
    237   delete M;
    238   return true;
    239 }
    240 
    241 Module*
    242 llvm::GetBitcodeSymbols(const char *BufPtr, unsigned Length,
    243                         const std::string& ModuleID,
    244                         LLVMContext& Context,
    245                         std::vector<std::string>& symbols,
    246                         std::string* ErrMsg) {
    247   // Get the module.
    248   OwningPtr<MemoryBuffer> Buffer(
    249     MemoryBuffer::getMemBufferCopy(StringRef(BufPtr, Length),ModuleID.c_str()));
    250 
    251   Module *M = ParseBitcodeFile(Buffer.get(), Context, ErrMsg);
    252   if (!M)
    253     return 0;
    254 
    255   // Get the symbols
    256   getSymbols(M, symbols);
    257 
    258   // Done with the module. Note that it's the caller's responsibility to delete
    259   // the Module.
    260   return M;
    261 }
    262