LLVM API Documentation
00001 //===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This header file implements the operating system Path concept. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/System/Path.h" 00015 #include "llvm/Config/config.h" 00016 #include <cassert> 00017 #include <cstring> 00018 #include <ostream> 00019 using namespace llvm; 00020 using namespace sys; 00021 00022 //===----------------------------------------------------------------------===// 00023 //=== WARNING: Implementation here must contain only TRULY operating system 00024 //=== independent code. 00025 //===----------------------------------------------------------------------===// 00026 00027 bool Path::operator==(const Path &that) const { 00028 return path == that.path; 00029 } 00030 00031 bool Path::operator!=(const Path &that) const { 00032 return path != that.path; 00033 } 00034 00035 bool Path::operator<(const Path& that) const { 00036 return path < that.path; 00037 } 00038 00039 std::ostream& llvm::operator<<(std::ostream &strm, const sys::Path &aPath) { 00040 strm << aPath.toString(); 00041 return strm; 00042 } 00043 00044 Path 00045 Path::GetLLVMConfigDir() { 00046 Path result; 00047 #ifdef LLVM_ETCDIR 00048 if (result.set(LLVM_ETCDIR)) 00049 return result; 00050 #endif 00051 return GetLLVMDefaultConfigDir(); 00052 } 00053 00054 LLVMFileType 00055 sys::IdentifyFileType(const char *magic, unsigned length) { 00056 assert(magic && "Invalid magic number string"); 00057 assert(length >=4 && "Invalid magic number length"); 00058 switch (magic[0]) { 00059 case 0xDE: // 0x0B17C0DE = BC wraper 00060 if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && 00061 magic[3] == (char)0x0B) 00062 return Bitcode_FileType; 00063 break; 00064 case 'B': 00065 if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE) 00066 return Bitcode_FileType; 00067 break; 00068 case '!': 00069 if (length >= 8) 00070 if (memcmp(magic,"!<arch>\n",8) == 0) 00071 return Archive_FileType; 00072 break; 00073 00074 case '\177': 00075 if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') { 00076 if (length >= 18 && magic[17] == 0) 00077 switch (magic[16]) { 00078 default: break; 00079 case 1: return ELF_Relocatable_FileType; 00080 case 2: return ELF_Executable_FileType; 00081 case 3: return ELF_SharedObject_FileType; 00082 case 4: return ELF_Core_FileType; 00083 } 00084 } 00085 break; 00086 00087 case 0xCA: 00088 if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && 00089 magic[3] == char(0xBE)) { 00090 // This is complicated by an overlap with Java class files. 00091 // See the Mach-O section in /usr/share/file/magic for details. 00092 if (length >= 8 && magic[7] < 43) 00093 // FIXME: Universal Binary of any type. 00094 return Mach_O_DynamicallyLinkedSharedLib_FileType; 00095 } 00096 break; 00097 00098 case 0xFE: 00099 case 0xCE: { 00100 uint16_t type = 0; 00101 if (magic[0] == char(0xFE) && magic[1] == char(0xED) && 00102 magic[2] == char(0xFA) && magic[3] == char(0xCE)) { 00103 /* Native endian */ 00104 if (length >= 16) type = magic[14] << 8 | magic[15]; 00105 } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) && 00106 magic[2] == char(0xED) && magic[3] == char(0xFE)) { 00107 /* Reverse endian */ 00108 if (length >= 14) type = magic[13] << 8 | magic[12]; 00109 } 00110 switch (type) { 00111 default: break; 00112 case 1: return Mach_O_Object_FileType; 00113 case 2: return Mach_O_Executable_FileType; 00114 case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType; 00115 case 4: return Mach_O_Core_FileType; 00116 case 5: return Mach_O_PreloadExectuable_FileType; 00117 case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType; 00118 case 7: return Mach_O_DynamicLinker_FileType; 00119 case 8: return Mach_O_Bundle_FileType; 00120 case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType; 00121 case 10: break; // FIXME: MH_DSYM companion file with only debug. 00122 } 00123 break; 00124 } 00125 case 0xF0: // PowerPC Windows 00126 case 0x83: // Alpha 32-bit 00127 case 0x84: // Alpha 64-bit 00128 case 0x66: // MPS R4000 Windows 00129 case 0x50: // mc68K 00130 case 0x4c: // 80386 Windows 00131 if (magic[1] == 0x01) 00132 return COFF_FileType; 00133 00134 case 0x90: // PA-RISC Windows 00135 case 0x68: // mc68K Windows 00136 if (magic[1] == 0x02) 00137 return COFF_FileType; 00138 break; 00139 00140 default: 00141 break; 00142 } 00143 return Unknown_FileType; 00144 } 00145 00146 bool 00147 Path::isArchive() const { 00148 if (canRead()) 00149 return hasMagicNumber("!<arch>\012"); 00150 return false; 00151 } 00152 00153 bool 00154 Path::isDynamicLibrary() const { 00155 if (canRead()) { 00156 std::string Magic; 00157 if (getMagicNumber(Magic, 64)) 00158 switch (IdentifyFileType(Magic.c_str(), 00159 static_cast<unsigned>(Magic.length()))) { 00160 default: return false; 00161 case Mach_O_FixedVirtualMemorySharedLib_FileType: 00162 case Mach_O_DynamicallyLinkedSharedLib_FileType: 00163 case Mach_O_DynamicallyLinkedSharedLibStub_FileType: 00164 case ELF_SharedObject_FileType: 00165 case COFF_FileType: return true; 00166 } 00167 } 00168 return false; 00169 } 00170 00171 Path 00172 Path::FindLibrary(std::string& name) { 00173 std::vector<sys::Path> LibPaths; 00174 GetSystemLibraryPaths(LibPaths); 00175 for (unsigned i = 0; i < LibPaths.size(); ++i) { 00176 sys::Path FullPath(LibPaths[i]); 00177 FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT); 00178 if (FullPath.isDynamicLibrary()) 00179 return FullPath; 00180 FullPath.eraseSuffix(); 00181 FullPath.appendSuffix("a"); 00182 if (FullPath.isArchive()) 00183 return FullPath; 00184 } 00185 return sys::Path(); 00186 } 00187 00188 std::string Path::GetDLLSuffix() { 00189 return LTDL_SHLIB_EXT; 00190 } 00191 00192 bool 00193 Path::isBitcodeFile() const { 00194 std::string actualMagic; 00195 if (!getMagicNumber(actualMagic, 4)) 00196 return false; 00197 LLVMFileType FT = 00198 IdentifyFileType(actualMagic.c_str(), 00199 static_cast<unsigned>(actualMagic.length())); 00200 return FT == Bitcode_FileType; 00201 } 00202 00203 bool Path::hasMagicNumber(const std::string &Magic) const { 00204 std::string actualMagic; 00205 if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size()))) 00206 return Magic == actualMagic; 00207 return false; 00208 } 00209 00210 static void getPathList(const char*path, std::vector<Path>& Paths) { 00211 const char* at = path; 00212 const char* delim = strchr(at, PathSeparator); 00213 Path tmpPath; 00214 while (delim != 0) { 00215 std::string tmp(at, size_t(delim-at)); 00216 if (tmpPath.set(tmp)) 00217 if (tmpPath.canRead()) 00218 Paths.push_back(tmpPath); 00219 at = delim + 1; 00220 delim = strchr(at, PathSeparator); 00221 } 00222 00223 if (*at != 0) 00224 if (tmpPath.set(std::string(at))) 00225 if (tmpPath.canRead()) 00226 Paths.push_back(tmpPath); 00227 } 00228 00229 static std::string getDirnameCharSep(const std::string& path, char Sep) { 00230 00231 if (path.empty()) 00232 return "."; 00233 00234 // If the path is all slashes, return a single slash. 00235 // Otherwise, remove all trailing slashes. 00236 00237 signed pos = static_cast<signed>(path.size()) - 1; 00238 00239 while (pos >= 0 && path[pos] == Sep) 00240 --pos; 00241 00242 if (pos < 0) 00243 return path[0] == Sep ? std::string(1, Sep) : std::string("."); 00244 00245 // Any slashes left? 00246 signed i = 0; 00247 00248 while (i < pos && path[i] != Sep) 00249 ++i; 00250 00251 if (i == pos) // No slashes? Return "." 00252 return "."; 00253 00254 // There is at least one slash left. Remove all trailing non-slashes. 00255 while (pos >= 0 && path[pos] != Sep) 00256 --pos; 00257 00258 // Remove any trailing slashes. 00259 while (pos >= 0 && path[pos] == Sep) 00260 --pos; 00261 00262 if (pos < 0) 00263 return path[0] == Sep ? std::string(1, Sep) : std::string("."); 00264 00265 return path.substr(0, pos+1); 00266 } 00267 00268 // Include the truly platform-specific parts of this class. 00269 #if defined(LLVM_ON_UNIX) 00270 #include "Unix/Path.inc" 00271 #endif 00272 #if defined(LLVM_ON_WIN32) 00273 #include "Win32/Path.inc" 00274 #endif 00275
This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.