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