Archive.cpp revision 6b8a63ae583b53a942dca7c681f4cf161c90d35e
1//===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Reid Spencer and is distributed under the 6// University of Illinois Open Source 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/ModuleProvider.h" 17#include "llvm/System/Process.h" 18 19using namespace llvm; 20 21// getMemberSize - compute the actual physical size of the file member as seen 22// on disk. This isn't the size of member's payload. Use getSize() for that. 23unsigned 24ArchiveMember::getMemberSize() const { 25 // Basically its the file size plus the header size 26 unsigned result = info.fileSize + sizeof(ArchiveMemberHeader); 27 28 // If it has a long filename, include the name length 29 if (hasLongFilename()) 30 result += path.toString().length() + 1; 31 32 // If its now odd lengthed, include the padding byte 33 if (result % 2 != 0 ) 34 result++; 35 36 return result; 37} 38 39// This default constructor is only use by the ilist when it creates its 40// sentry node. We give it specific static values to make it stand out a bit. 41ArchiveMember::ArchiveMember() 42 : next(0), prev(0), parent(0), path("<invalid>"), flags(0), data(0) 43{ 44 info.user = sys::Process::GetCurrentUserId(); 45 info.group = sys::Process::GetCurrentGroupId(); 46 info.mode = 0777; 47 info.fileSize = 0; 48 info.modTime = sys::TimeValue::now(); 49} 50 51// This is the constructor that the Archive class uses when it is building or 52// reading an archive. It just defaults a few things and ensures the parent is 53// set for the iplist. The Archive class fills in the ArchiveMember's data. 54// This is required because correctly setting the data may depend on other 55// things in the Archive. 56ArchiveMember::ArchiveMember(Archive* PAR) 57 : next(0), prev(0), parent(PAR), path(), flags(0), data(0) 58{ 59} 60 61// This method allows an ArchiveMember to be replaced with the data for a 62// different file, presumably as an update to the member. It also makes sure 63// the flags are reset correctly. 64void ArchiveMember::replaceWith(const sys::Path& newFile) { 65 assert(newFile.exists() && "Can't replace with a non-existent file"); 66 data = 0; 67 path = newFile; 68 69 // SVR4 symbol tables have an empty name 70 if (path.toString() == ARFILE_SVR4_SYMTAB_NAME) 71 flags |= SVR4SymbolTableFlag; 72 else 73 flags &= ~SVR4SymbolTableFlag; 74 75 // BSD4.4 symbol tables have a special name 76 if (path.toString() == ARFILE_BSD4_SYMTAB_NAME) 77 flags |= BSD4SymbolTableFlag; 78 else 79 flags &= ~BSD4SymbolTableFlag; 80 81 // LLVM symbol tables have a very specific name 82 if (path.toString() == ARFILE_LLVM_SYMTAB_NAME) 83 flags |= LLVMSymbolTableFlag; 84 else 85 flags &= ~LLVMSymbolTableFlag; 86 87 // String table name 88 if (path.toString() == ARFILE_STRTAB_NAME) 89 flags |= StringTableFlag; 90 else 91 flags &= ~StringTableFlag; 92 93 // If it has a slash then it has a path 94 bool hasSlash = path.toString().find('/') != std::string::npos; 95 if (hasSlash) 96 flags |= HasPathFlag; 97 else 98 flags &= ~HasPathFlag; 99 100 // If it has a slash or its over 15 chars then its a long filename format 101 if (hasSlash || path.toString().length() > 15) 102 flags |= HasLongFilenameFlag; 103 else 104 flags &= ~HasLongFilenameFlag; 105 106 // Get the signature and status info 107 std::string magic; 108 const char* signature = (const char*) data; 109 if (!signature) { 110 path.getMagicNumber(magic,4); 111 signature = magic.c_str(); 112 path.getStatusInfo(info); 113 } 114 115 // Determine what kind of file it is 116 switch (sys::IdentifyFileType(signature,4)) { 117 case sys::BytecodeFileType: 118 flags |= BytecodeFlag; 119 break; 120 case sys::CompressedBytecodeFileType: 121 flags |= CompressedBytecodeFlag; 122 flags &= ~CompressedFlag; 123 break; 124 default: 125 flags &= ~(BytecodeFlag|CompressedBytecodeFlag); 126 break; 127 } 128} 129 130// Archive constructor - this is the only constructor that gets used for the 131// Archive class. Everything else (default,copy) is deprecated. This just 132// initializes and maps the file into memory, if requested. 133Archive::Archive(const sys::Path& filename, bool map ) 134 : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), 135 symTabSize(0), firstFileOffset(0), modules(), foreignST(0) 136{ 137 if (map) { 138 mapfile = new sys::MappedFile(filename); 139 base = (char*) mapfile->map(); 140 } 141} 142 143// Archive destructor - just clean up memory 144Archive::~Archive() { 145 // Shutdown the file mapping 146 if (mapfile) { 147 mapfile->close(); 148 delete mapfile; 149 } 150 // Delete any ModuleProviders and ArchiveMember's we've allocated as a result 151 // of symbol table searches. 152 for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) { 153 delete I->second.first; 154 delete I->second.second; 155 } 156} 157 158