diff options
Diffstat (limited to 'lib/Bytecode/Archive/Archive.cpp')
-rw-r--r-- | lib/Bytecode/Archive/Archive.cpp | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/lib/Bytecode/Archive/Archive.cpp b/lib/Bytecode/Archive/Archive.cpp index e9fcd2ebe1..b006e5a83d 100644 --- a/lib/Bytecode/Archive/Archive.cpp +++ b/lib/Bytecode/Archive/Archive.cpp @@ -7,18 +7,144 @@ // //===----------------------------------------------------------------------===// // -// Builds up standard unix archive files (.a) containing LLVM bytecode. +// This file contains the implementation of the Archive and ArchiveMember +// classes that is common to both reading and writing archives.. // //===----------------------------------------------------------------------===// #include "ArchiveInternals.h" +#include "llvm/ModuleProvider.h" using namespace llvm; -Archive::Archive() { +// getMemberSize - compute the actual physical size of the file member as seen +// on disk. This isn't the size of member's payload. Use getSize() for that. +unsigned +ArchiveMember::getMemberSize() const { + // Basically its the file size plus the header size + unsigned result = info.fileSize + sizeof(ArchiveMemberHeader); + + // If it has a long filename, include the name length + if (hasLongFilename()) + result += path.get().length() + 1; + + // If its now odd lengthed, include the padding byte + if (result % 2 != 0 ) + result++; + + return result; +} + +// 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("<invalid>"), flags(0), data(0) +{ + info.user = 1000; + info.group = 1000; + 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 +// things in the Archive. +ArchiveMember::ArchiveMember(Archive* PAR) + : next(0), prev(0), parent(PAR), path(), flags(0), data(0) +{ +} + +// 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"); + data = 0; + path = newFile; + + // Foreign symbol tables have an empty name + if (path.get() == ARFILE_SYMTAB_NAME) + flags |= ForeignSymbolTableFlag; + else + flags &= ~ForeignSymbolTableFlag; + + // LLVM symbol tables have a very specific name + if (path.get() == ARFILE_LLVM_SYMTAB_NAME) + flags |= LLVMSymbolTableFlag; + else + flags &= ~LLVMSymbolTableFlag; + + // String table name + if (path.get() == 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; + 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) + flags |= HasLongFilenameFlag; + else + flags &= ~HasLongFilenameFlag; + + // Get the signature and status info + std::string magic; + const char* signature = (const char*) data; + if (!signature) { + path.getMagicNumber(magic,4); + signature = magic.c_str(); + path.getStatusInfo(info); + } + + // 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); + break; + } +} + +// Archive constructor - this is the only constructor that gets used for the +// 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 ) + : archPath(filename), members(), mapfile(0), base(0), symTab(), symTabSize(0) +{ + if (map) { + mapfile = new sys::MappedFile(filename); + base = (char*) mapfile->map(); + } } +// Archive destructor - just clean up memory Archive::~Archive() { + // Shutdown the file mapping + if (mapfile) { + mapfile->unmap(); + delete mapfile; + } + // 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 ) { + delete I->second.first; + delete I->second.second; + } } // vim: sw=2 ai |