LLVM API Documentation
00001 //===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by Reid Spencer and is distributed under the 00006 // University of Illinois Open Source 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/ModuleProvider.h" 00017 #include "llvm/System/Process.h" 00018 00019 using namespace llvm; 00020 00021 // getMemberSize - compute the actual physical size of the file member as seen 00022 // on disk. This isn't the size of member's payload. Use getSize() for that. 00023 unsigned 00024 ArchiveMember::getMemberSize() const { 00025 // Basically its the file size plus the header size 00026 unsigned result = info.fileSize + sizeof(ArchiveMemberHeader); 00027 00028 // If it has a long filename, include the name length 00029 if (hasLongFilename()) 00030 result += path.toString().length() + 1; 00031 00032 // If its now odd lengthed, include the padding byte 00033 if (result % 2 != 0 ) 00034 result++; 00035 00036 return result; 00037 } 00038 00039 // This default constructor is only use by the ilist when it creates its 00040 // sentry node. We give it specific static values to make it stand out a bit. 00041 ArchiveMember::ArchiveMember() 00042 : next(0), prev(0), parent(0), path("--invalid--"), flags(0), data(0) 00043 { 00044 info.user = sys::Process::GetCurrentUserId(); 00045 info.group = sys::Process::GetCurrentGroupId(); 00046 info.mode = 0777; 00047 info.fileSize = 0; 00048 info.modTime = sys::TimeValue::now(); 00049 } 00050 00051 // This is the constructor that the Archive class uses when it is building or 00052 // reading an archive. It just defaults a few things and ensures the parent is 00053 // set for the iplist. The Archive class fills in the ArchiveMember's data. 00054 // This is required because correctly setting the data may depend on other 00055 // things in the Archive. 00056 ArchiveMember::ArchiveMember(Archive* PAR) 00057 : next(0), prev(0), parent(PAR), path(), flags(0), data(0) 00058 { 00059 } 00060 00061 // This method allows an ArchiveMember to be replaced with the data for a 00062 // different file, presumably as an update to the member. It also makes sure 00063 // the flags are reset correctly. 00064 void ArchiveMember::replaceWith(const sys::Path& newFile) { 00065 assert(newFile.exists() && "Can't replace with a non-existent file"); 00066 data = 0; 00067 path = newFile; 00068 00069 // SVR4 symbol tables have an empty name 00070 if (path.toString() == ARFILE_SVR4_SYMTAB_NAME) 00071 flags |= SVR4SymbolTableFlag; 00072 else 00073 flags &= ~SVR4SymbolTableFlag; 00074 00075 // BSD4.4 symbol tables have a special name 00076 if (path.toString() == ARFILE_BSD4_SYMTAB_NAME) 00077 flags |= BSD4SymbolTableFlag; 00078 else 00079 flags &= ~BSD4SymbolTableFlag; 00080 00081 // LLVM symbol tables have a very specific name 00082 if (path.toString() == ARFILE_LLVM_SYMTAB_NAME) 00083 flags |= LLVMSymbolTableFlag; 00084 else 00085 flags &= ~LLVMSymbolTableFlag; 00086 00087 // String table name 00088 if (path.toString() == ARFILE_STRTAB_NAME) 00089 flags |= StringTableFlag; 00090 else 00091 flags &= ~StringTableFlag; 00092 00093 // If it has a slash then it has a path 00094 bool hasSlash = path.toString().find('/') != std::string::npos; 00095 if (hasSlash) 00096 flags |= HasPathFlag; 00097 else 00098 flags &= ~HasPathFlag; 00099 00100 // If it has a slash or its over 15 chars then its a long filename format 00101 if (hasSlash || path.toString().length() > 15) 00102 flags |= HasLongFilenameFlag; 00103 else 00104 flags &= ~HasLongFilenameFlag; 00105 00106 // Get the signature and status info 00107 std::string magic; 00108 const char* signature = (const char*) data; 00109 if (!signature) { 00110 path.getMagicNumber(magic,4); 00111 signature = magic.c_str(); 00112 path.getStatusInfo(info); 00113 } 00114 00115 // Determine what kind of file it is 00116 switch (sys::IdentifyFileType(signature,4)) { 00117 case sys::BytecodeFileType: 00118 flags |= BytecodeFlag; 00119 break; 00120 case sys::CompressedBytecodeFileType: 00121 flags |= CompressedBytecodeFlag; 00122 flags &= ~CompressedFlag; 00123 break; 00124 default: 00125 flags &= ~(BytecodeFlag|CompressedBytecodeFlag); 00126 break; 00127 } 00128 } 00129 00130 // Archive constructor - this is the only constructor that gets used for the 00131 // Archive class. Everything else (default,copy) is deprecated. This just 00132 // initializes and maps the file into memory, if requested. 00133 Archive::Archive(const sys::Path& filename, bool map ) 00134 : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), 00135 symTabSize(0), firstFileOffset(0), modules(), foreignST(0) 00136 { 00137 if (map) { 00138 mapfile = new sys::MappedFile(filename); 00139 base = (char*) mapfile->map(); 00140 } 00141 } 00142 00143 void Archive::cleanUpMemory() { 00144 // Shutdown the file mapping 00145 if (mapfile) { 00146 mapfile->close(); 00147 delete mapfile; 00148 00149 mapfile = 0; 00150 base = 0; 00151 } 00152 00153 // Forget the entire symbol table 00154 symTab.clear(); 00155 symTabSize = 0; 00156 00157 firstFileOffset = 0; 00158 00159 // Free the foreign symbol table member 00160 if (foreignST) { 00161 delete foreignST; 00162 foreignST = 0; 00163 } 00164 00165 // Delete any ModuleProviders and ArchiveMember's we've allocated as a result 00166 // of symbol table searches. 00167 for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) { 00168 delete I->second.first; 00169 delete I->second.second; 00170 } 00171 } 00172 00173 // Archive destructor - just clean up memory 00174 Archive::~Archive() { 00175 cleanUpMemory(); 00176 } 00177