LLVM API Documentation

Archive.cpp

Go to the documentation of this file.
00001 //===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains the implementation of the Archive and ArchiveMember
00011 // classes that is common to both reading and writing archives..
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "ArchiveInternals.h"
00016 #include "llvm/Bitcode/ReaderWriter.h"
00017 #include "llvm/ModuleProvider.h"
00018 #include "llvm/Module.h"
00019 #include "llvm/Support/MemoryBuffer.h"
00020 #include "llvm/System/Process.h"
00021 #include <memory>
00022 #include <cstring>
00023 using namespace llvm;
00024 
00025 // getMemberSize - compute the actual physical size of the file member as seen
00026 // on disk. This isn't the size of member's payload. Use getSize() for that.
00027 unsigned
00028 ArchiveMember::getMemberSize() const {
00029   // Basically its the file size plus the header size
00030   unsigned result =  info.fileSize + sizeof(ArchiveMemberHeader);
00031 
00032   // If it has a long filename, include the name length
00033   if (hasLongFilename())
00034     result += path.toString().length() + 1;
00035 
00036   // If its now odd lengthed, include the padding byte
00037   if (result % 2 != 0 )
00038     result++;
00039 
00040   return result;
00041 }
00042 
00043 // This default constructor is only use by the ilist when it creates its
00044 // sentry node. We give it specific static values to make it stand out a bit.
00045 ArchiveMember::ArchiveMember()
00046   : parent(0), path("--invalid--"), flags(0), data(0)
00047 {
00048   info.user = sys::Process::GetCurrentUserId();
00049   info.group = sys::Process::GetCurrentGroupId();
00050   info.mode = 0777;
00051   info.fileSize = 0;
00052   info.modTime = sys::TimeValue::now();
00053 }
00054 
00055 // This is the constructor that the Archive class uses when it is building or
00056 // reading an archive. It just defaults a few things and ensures the parent is
00057 // set for the iplist. The Archive class fills in the ArchiveMember's data.
00058 // This is required because correctly setting the data may depend on other
00059 // things in the Archive.
00060 ArchiveMember::ArchiveMember(Archive* PAR)
00061   : parent(PAR), path(), flags(0), data(0)
00062 {
00063 }
00064 
00065 // This method allows an ArchiveMember to be replaced with the data for a
00066 // different file, presumably as an update to the member. It also makes sure
00067 // the flags are reset correctly.
00068 bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
00069   if (!newFile.exists()) {
00070     if (ErrMsg) 
00071       *ErrMsg = "Can not replace an archive member with a non-existent file";
00072     return true;
00073   }
00074 
00075   data = 0;
00076   path = newFile;
00077 
00078   // SVR4 symbol tables have an empty name
00079   if (path.toString() == ARFILE_SVR4_SYMTAB_NAME)
00080     flags |= SVR4SymbolTableFlag;
00081   else
00082     flags &= ~SVR4SymbolTableFlag;
00083 
00084   // BSD4.4 symbol tables have a special name
00085   if (path.toString() == ARFILE_BSD4_SYMTAB_NAME)
00086     flags |= BSD4SymbolTableFlag;
00087   else
00088     flags &= ~BSD4SymbolTableFlag;
00089 
00090   // LLVM symbol tables have a very specific name
00091   if (path.toString() == ARFILE_LLVM_SYMTAB_NAME)
00092     flags |= LLVMSymbolTableFlag;
00093   else
00094     flags &= ~LLVMSymbolTableFlag;
00095 
00096   // String table name
00097   if (path.toString() == ARFILE_STRTAB_NAME)
00098     flags |= StringTableFlag;
00099   else
00100     flags &= ~StringTableFlag;
00101 
00102   // If it has a slash then it has a path
00103   bool hasSlash = path.toString().find('/') != std::string::npos;
00104   if (hasSlash)
00105     flags |= HasPathFlag;
00106   else
00107     flags &= ~HasPathFlag;
00108 
00109   // If it has a slash or its over 15 chars then its a long filename format
00110   if (hasSlash || path.toString().length() > 15)
00111     flags |= HasLongFilenameFlag;
00112   else
00113     flags &= ~HasLongFilenameFlag;
00114 
00115   // Get the signature and status info
00116   const char* signature = (const char*) data;
00117   std::string magic;
00118   if (!signature) {
00119     path.getMagicNumber(magic,4);
00120     signature = magic.c_str();
00121     std::string err;
00122     const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg);
00123     if (FSinfo)
00124       info = *FSinfo;
00125     else
00126       return true;
00127   }
00128 
00129   // Determine what kind of file it is
00130   switch (sys::IdentifyFileType(signature,4)) {
00131     default:
00132       flags &= ~BitcodeFlag;
00133       break;
00134   }
00135   return false;
00136 }
00137 
00138 // Archive constructor - this is the only constructor that gets used for the
00139 // Archive class. Everything else (default,copy) is deprecated. This just
00140 // initializes and maps the file into memory, if requested.
00141 Archive::Archive(const sys::Path& filename)
00142   : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
00143     symTabSize(0), firstFileOffset(0), modules(), foreignST(0) {
00144 }
00145 
00146 bool
00147 Archive::mapToMemory(std::string* ErrMsg) {
00148   mapfile = MemoryBuffer::getFile(archPath.c_str(), ErrMsg);
00149   if (mapfile == 0)
00150     return true;
00151   base = mapfile->getBufferStart();
00152   return false;
00153 }
00154 
00155 void Archive::cleanUpMemory() {
00156   // Shutdown the file mapping
00157   delete mapfile;
00158   mapfile = 0;
00159   base = 0;
00160   
00161   // Forget the entire symbol table
00162   symTab.clear();
00163   symTabSize = 0;
00164   
00165   firstFileOffset = 0;
00166   
00167   // Free the foreign symbol table member
00168   if (foreignST) {
00169     delete foreignST;
00170     foreignST = 0;
00171   }
00172   
00173   // Delete any ModuleProviders and ArchiveMember's we've allocated as a result
00174   // of symbol table searches.
00175   for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) {
00176     delete I->second.first;
00177     delete I->second.second;
00178   }
00179 }
00180 
00181 // Archive destructor - just clean up memory
00182 Archive::~Archive() {
00183   cleanUpMemory();
00184 }
00185 
00186 
00187 
00188 static void getSymbols(Module*M, std::vector<std::string>& symbols) {
00189   // Loop over global variables
00190   for (Module::global_iterator GI = M->global_begin(), GE=M->global_end(); GI != GE; ++GI)
00191     if (!GI->isDeclaration() && !GI->hasLocalLinkage())
00192       if (!GI->getName().empty())
00193         symbols.push_back(GI->getName());
00194   
00195   // Loop over functions
00196   for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI)
00197     if (!FI->isDeclaration() && !FI->hasLocalLinkage())
00198       if (!FI->getName().empty())
00199         symbols.push_back(FI->getName());
00200 
00201   // Loop over aliases
00202   for (Module::alias_iterator AI = M->alias_begin(), AE = M->alias_end();
00203        AI != AE; ++AI) {
00204     if (AI->hasName())
00205       symbols.push_back(AI->getName());
00206   }
00207 }
00208 
00209 // Get just the externally visible defined symbols from the bitcode
00210 bool llvm::GetBitcodeSymbols(const sys::Path& fName,
00211                              std::vector<std::string>& symbols,
00212                              std::string* ErrMsg) {
00213   std::auto_ptr<MemoryBuffer> Buffer(
00214                        MemoryBuffer::getFileOrSTDIN(fName.c_str()));
00215   if (!Buffer.get()) {
00216     if (ErrMsg) *ErrMsg = "Could not open file '" + fName.toString() + "'";
00217     return true;
00218   }
00219   
00220   ModuleProvider *MP = getBitcodeModuleProvider(Buffer.get(), ErrMsg);
00221   if (!MP)
00222     return true;
00223   
00224   // Get the module from the provider
00225   Module* M = MP->materializeModule();
00226   if (M == 0) {
00227     delete MP;
00228     return true;
00229   }
00230   
00231   // Get the symbols
00232   getSymbols(M, symbols);
00233   
00234   // Done with the module.
00235   delete MP;
00236   return true;
00237 }
00238 
00239 ModuleProvider*
00240 llvm::GetBitcodeSymbols(const unsigned char *BufPtr, unsigned Length,
00241                         const std::string& ModuleID,
00242                         std::vector<std::string>& symbols,
00243                         std::string* ErrMsg) {
00244   // Get the module provider
00245   MemoryBuffer *Buffer =MemoryBuffer::getNewMemBuffer(Length, ModuleID.c_str());
00246   memcpy((char*)Buffer->getBufferStart(), BufPtr, Length);
00247   
00248   ModuleProvider *MP = getBitcodeModuleProvider(Buffer, ErrMsg);
00249   if (!MP)
00250     return 0;
00251   
00252   // Get the module from the provider
00253   Module* M = MP->materializeModule();
00254   if (M == 0) {
00255     delete MP;
00256     return 0;
00257   }
00258   
00259   // Get the symbols
00260   getSymbols(M, symbols);
00261   
00262   // Done with the module. Note that ModuleProvider will delete the
00263   // Module when it is deleted. Also note that its the caller's responsibility
00264   // to delete the ModuleProvider.
00265   return MP;
00266 }