X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FArchive%2FArchive.cpp;h=c6c89d27dbb0ab78592953e2542de3da5ca077eb;hb=d8e880c670699bd56dc3968647a4b963793d201d;hp=a3fb534c9c36433a7661c7997b97cbce34e0bb4d;hpb=1f465809cdc9fef41b756731821226a16dfbb8b4;p=oota-llvm.git diff --git a/lib/Archive/Archive.cpp b/lib/Archive/Archive.cpp index a3fb534c9c3..c6c89d27dbb 100644 --- a/lib/Archive/Archive.cpp +++ b/lib/Archive/Archive.cpp @@ -1,10 +1,10 @@ //===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===// -// +// // The LLVM Compiler Infrastructure // -// This file was developed by Reid Spencer and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. -// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// //===----------------------------------------------------------------------===// // // This file contains the implementation of the Archive and ArchiveMember @@ -13,8 +13,13 @@ //===----------------------------------------------------------------------===// #include "ArchiveInternals.h" +#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/ModuleProvider.h" - +#include "llvm/Module.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/System/Process.h" +#include +#include using namespace llvm; // getMemberSize - compute the actual physical size of the file member as seen @@ -26,10 +31,10 @@ ArchiveMember::getMemberSize() const { // If it has a long filename, include the name length if (hasLongFilename()) - result += path.get().length() + 1; + result += path.toString().length() + 1; // If its now odd lengthed, include the padding byte - if (result % 2 != 0 ) + if (result % 2 != 0 ) result++; return result; @@ -37,109 +42,134 @@ ArchiveMember::getMemberSize() const { // This default constructor is only use by the ilist when it creates its // sentry node. We give it specific static values to make it stand out a bit. -ArchiveMember::ArchiveMember() - : next(0), prev(0), parent(0), path(""), flags(0), data(0) +ArchiveMember::ArchiveMember() + : parent(0), path("--invalid--"), flags(0), data(0) { - info.user = 1000; - info.group = 1000; - info.mode = 0777; - info.fileSize = 0; + info.user = sys::Process::GetCurrentUserId(); + info.group = sys::Process::GetCurrentGroupId(); + info.mode = 0777; + info.fileSize = 0; info.modTime = sys::TimeValue::now(); } // This is the constructor that the Archive class uses when it is building or // reading an archive. It just defaults a few things and ensures the parent is -// set for the iplist. The Archive class fills in the ArchiveMember's data. -// This is required because correctly setting the data may depend on other +// set for the iplist. The Archive class fills in the ArchiveMember's data. +// This is required because correctly setting the data may depend on other // things in the Archive. ArchiveMember::ArchiveMember(Archive* PAR) - : next(0), prev(0), parent(PAR), path(), flags(0), data(0) + : parent(PAR), path(), flags(0), data(0) { } -// This method allows an ArchiveMember to be replaced with the data for a +// This method allows an ArchiveMember to be replaced with the data for a // different file, presumably as an update to the member. It also makes sure // the flags are reset correctly. -void ArchiveMember::replaceWith(const sys::Path& newFile) { - assert(newFile.exists() && "Can't replace with a non-existent file"); +bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) { + if (!newFile.exists()) { + if (ErrMsg) + *ErrMsg = "Can not replace an archive member with a non-existent file"; + return true; + } + data = 0; path = newFile; - // Foreign symbol tables have an empty name - if (path.get() == ARFILE_SYMTAB_NAME) - flags |= ForeignSymbolTableFlag; + // SVR4 symbol tables have an empty name + if (path.toString() == ARFILE_SVR4_SYMTAB_NAME) + flags |= SVR4SymbolTableFlag; else - flags &= ~ForeignSymbolTableFlag; + flags &= ~SVR4SymbolTableFlag; + + // BSD4.4 symbol tables have a special name + if (path.toString() == ARFILE_BSD4_SYMTAB_NAME) + flags |= BSD4SymbolTableFlag; + else + flags &= ~BSD4SymbolTableFlag; // LLVM symbol tables have a very specific name - if (path.get() == ARFILE_LLVM_SYMTAB_NAME) + if (path.toString() == ARFILE_LLVM_SYMTAB_NAME) flags |= LLVMSymbolTableFlag; else flags &= ~LLVMSymbolTableFlag; // String table name - if (path.get() == ARFILE_STRTAB_NAME) + if (path.toString() == ARFILE_STRTAB_NAME) flags |= StringTableFlag; else flags &= ~StringTableFlag; // If it has a slash then it has a path - bool hasSlash = path.get().find('/') != std::string::npos; + bool hasSlash = path.toString().find('/') != std::string::npos; if (hasSlash) flags |= HasPathFlag; else flags &= ~HasPathFlag; // If it has a slash or its over 15 chars then its a long filename format - if (hasSlash || path.get().length() > 15) + if (hasSlash || path.toString().length() > 15) flags |= HasLongFilenameFlag; else flags &= ~HasLongFilenameFlag; // Get the signature and status info - std::string magic; const char* signature = (const char*) data; + std::string magic; if (!signature) { path.getMagicNumber(magic,4); signature = magic.c_str(); - path.getStatusInfo(info); + std::string err; + const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg); + if (FSinfo) + info = *FSinfo; + else + return true; } // Determine what kind of file it is switch (sys::IdentifyFileType(signature,4)) { - case sys::BytecodeFileType: - flags |= BytecodeFlag; - break; - case sys::CompressedBytecodeFileType: - flags |= CompressedBytecodeFlag; - flags &= ~CompressedFlag; - break; default: - flags &= ~(BytecodeFlag|CompressedBytecodeFlag); + flags &= ~BitcodeFlag; break; } + return false; } // Archive constructor - this is the only constructor that gets used for the -// Archive class. Everything else (default,copy) is deprecated. This just +// Archive class. Everything else (default,copy) is deprecated. This just // initializes and maps the file into memory, if requested. -Archive::Archive(const sys::Path& filename, bool map ) +Archive::Archive(const sys::Path& filename) : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), - symTabSize(0), firstFileOffset(0), modules(), foreignST(0) -{ - if (map) { - mapfile = new sys::MappedFile(filename); - base = (char*) mapfile->map(); - } + symTabSize(0), firstFileOffset(0), modules(), foreignST(0) { } -// Archive destructor - just clean up memory -Archive::~Archive() { +bool +Archive::mapToMemory(std::string* ErrMsg) { + mapfile = MemoryBuffer::getFile(archPath.c_str(), ErrMsg); + if (mapfile == 0) + return true; + base = mapfile->getBufferStart(); + return false; +} + +void Archive::cleanUpMemory() { // Shutdown the file mapping - if (mapfile) { - mapfile->unmap(); - delete mapfile; + delete mapfile; + mapfile = 0; + base = 0; + + // Forget the entire symbol table + symTab.clear(); + symTabSize = 0; + + firstFileOffset = 0; + + // Free the foreign symbol table member + if (foreignST) { + delete foreignST; + foreignST = 0; } + // Delete any ModuleProviders and ArchiveMember's we've allocated as a result // of symbol table searches. for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) { @@ -148,4 +178,89 @@ Archive::~Archive() { } } -// vim: sw=2 ai +// Archive destructor - just clean up memory +Archive::~Archive() { + cleanUpMemory(); +} + + + +static void getSymbols(Module*M, std::vector& symbols) { + // Loop over global variables + for (Module::global_iterator GI = M->global_begin(), GE=M->global_end(); GI != GE; ++GI) + if (!GI->isDeclaration() && !GI->hasLocalLinkage()) + if (!GI->getName().empty()) + symbols.push_back(GI->getName()); + + // Loop over functions + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) + if (!FI->isDeclaration() && !FI->hasLocalLinkage()) + if (!FI->getName().empty()) + symbols.push_back(FI->getName()); + + // Loop over aliases + for (Module::alias_iterator AI = M->alias_begin(), AE = M->alias_end(); + AI != AE; ++AI) { + if (AI->hasName()) + symbols.push_back(AI->getName()); + } +} + +// Get just the externally visible defined symbols from the bitcode +bool llvm::GetBitcodeSymbols(const sys::Path& fName, + std::vector& symbols, + std::string* ErrMsg) { + std::auto_ptr Buffer( + MemoryBuffer::getFileOrSTDIN(fName.c_str())); + if (!Buffer.get()) { + if (ErrMsg) *ErrMsg = "Could not open file '" + fName.toString() + "'"; + return true; + } + + ModuleProvider *MP = getBitcodeModuleProvider(Buffer.get(), ErrMsg); + if (!MP) + return true; + + // Get the module from the provider + Module* M = MP->materializeModule(); + if (M == 0) { + delete MP; + return true; + } + + // Get the symbols + getSymbols(M, symbols); + + // Done with the module. + delete MP; + return true; +} + +ModuleProvider* +llvm::GetBitcodeSymbols(const unsigned char *BufPtr, unsigned Length, + const std::string& ModuleID, + std::vector& symbols, + std::string* ErrMsg) { + // Get the module provider + MemoryBuffer *Buffer =MemoryBuffer::getNewMemBuffer(Length, ModuleID.c_str()); + memcpy((char*)Buffer->getBufferStart(), BufPtr, Length); + + ModuleProvider *MP = getBitcodeModuleProvider(Buffer, ErrMsg); + if (!MP) + return 0; + + // Get the module from the provider + Module* M = MP->materializeModule(); + if (M == 0) { + delete MP; + return 0; + } + + // Get the symbols + getSymbols(M, symbols); + + // Done with the module. Note that ModuleProvider will delete the + // Module when it is deleted. Also note that its the caller's responsibility + // to delete the ModuleProvider. + return MP; +}