Archive.cpp revision 0ff2d31766209ce1a69d4d2c5d35761ef57362aa
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. 64bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) { 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 const char* signature = (const char*) data; 108 std::string magic; 109 if (!signature) { 110 path.getMagicNumber(magic,4); 111 signature = magic.c_str(); 112 std::string err; 113 if (path.getFileStatus(info, ErrMsg)) 114 return true; 115 } 116 117 // Determine what kind of file it is 118 switch (sys::IdentifyFileType(signature,4)) { 119 case sys::BytecodeFileType: 120 flags |= BytecodeFlag; 121 break; 122 case sys::CompressedBytecodeFileType: 123 flags |= CompressedBytecodeFlag; 124 flags &= ~CompressedFlag; 125 break; 126 default: 127 flags &= ~(BytecodeFlag|CompressedBytecodeFlag); 128 break; 129 } 130 return false; 131} 132 133// Archive constructor - this is the only constructor that gets used for the 134// Archive class. Everything else (default,copy) is deprecated. This just 135// initializes and maps the file into memory, if requested. 136Archive::Archive(const sys::Path& filename) 137 : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), 138 symTabSize(0), firstFileOffset(0), modules(), foreignST(0) 139{ 140} 141 142bool 143Archive::mapToMemory(std::string* ErrMsg) 144{ 145 mapfile = new sys::MappedFile(); 146 if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg)) 147 return true; 148 if (!(base = (char*) mapfile->map(ErrMsg))) 149 return true; 150 return false; 151} 152 153void Archive::cleanUpMemory() { 154 // Shutdown the file mapping 155 if (mapfile) { 156 mapfile->close(); 157 delete mapfile; 158 159 mapfile = 0; 160 base = 0; 161 } 162 163 // Forget the entire symbol table 164 symTab.clear(); 165 symTabSize = 0; 166 167 firstFileOffset = 0; 168 169 // Free the foreign symbol table member 170 if (foreignST) { 171 delete foreignST; 172 foreignST = 0; 173 } 174 175 // Delete any ModuleProviders and ArchiveMember's we've allocated as a result 176 // of symbol table searches. 177 for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) { 178 delete I->second.first; 179 delete I->second.second; 180 } 181} 182 183// Archive destructor - just clean up memory 184Archive::~Archive() { 185 cleanUpMemory(); 186} 187 188