1 //===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This header file implements the operating system Path concept. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/Path.h" 15 #include "llvm/Support/FileSystem.h" 16 #include "llvm/Config/config.h" 17 #include "llvm/Support/FileSystem.h" 18 #include <cassert> 19 #include <cstring> 20 #include <ostream> 21 using namespace llvm; 22 using namespace sys; 23 24 //===----------------------------------------------------------------------===// 25 //=== WARNING: Implementation here must contain only TRULY operating system 26 //=== independent code. 27 //===----------------------------------------------------------------------===// 28 29 bool Path::operator==(const Path &that) const { 30 return path == that.path; 31 } 32 33 bool Path::operator<(const Path& that) const { 34 return path < that.path; 35 } 36 37 Path 38 Path::GetLLVMConfigDir() { 39 Path result; 40 #ifdef LLVM_ETCDIR 41 if (result.set(LLVM_ETCDIR)) 42 return result; 43 #endif 44 return GetLLVMDefaultConfigDir(); 45 } 46 47 LLVMFileType 48 sys::IdentifyFileType(const char *magic, unsigned length) { 49 assert(magic && "Invalid magic number string"); 50 assert(length >=4 && "Invalid magic number length"); 51 switch ((unsigned char)magic[0]) { 52 case 0xDE: // 0x0B17C0DE = BC wraper 53 if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && 54 magic[3] == (char)0x0B) 55 return Bitcode_FileType; 56 break; 57 case 'B': 58 if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE) 59 return Bitcode_FileType; 60 break; 61 case '!': 62 if (length >= 8) 63 if (memcmp(magic,"!<arch>\n",8) == 0) 64 return Archive_FileType; 65 break; 66 67 case '\177': 68 if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') { 69 if (length >= 18 && magic[17] == 0) 70 switch (magic[16]) { 71 default: break; 72 case 1: return ELF_Relocatable_FileType; 73 case 2: return ELF_Executable_FileType; 74 case 3: return ELF_SharedObject_FileType; 75 case 4: return ELF_Core_FileType; 76 } 77 } 78 break; 79 80 case 0xCA: 81 if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && 82 magic[3] == char(0xBE)) { 83 // This is complicated by an overlap with Java class files. 84 // See the Mach-O section in /usr/share/file/magic for details. 85 if (length >= 8 && magic[7] < 43) 86 // FIXME: Universal Binary of any type. 87 return Mach_O_DynamicallyLinkedSharedLib_FileType; 88 } 89 break; 90 91 case 0xFE: 92 case 0xCE: { 93 uint16_t type = 0; 94 if (magic[0] == char(0xFE) && magic[1] == char(0xED) && 95 magic[2] == char(0xFA) && magic[3] == char(0xCE)) { 96 /* Native endian */ 97 if (length >= 16) type = magic[14] << 8 | magic[15]; 98 } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) && 99 magic[2] == char(0xED) && magic[3] == char(0xFE)) { 100 /* Reverse endian */ 101 if (length >= 14) type = magic[13] << 8 | magic[12]; 102 } 103 switch (type) { 104 default: break; 105 case 1: return Mach_O_Object_FileType; 106 case 2: return Mach_O_Executable_FileType; 107 case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType; 108 case 4: return Mach_O_Core_FileType; 109 case 5: return Mach_O_PreloadExecutable_FileType; 110 case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType; 111 case 7: return Mach_O_DynamicLinker_FileType; 112 case 8: return Mach_O_Bundle_FileType; 113 case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType; 114 case 10: break; // FIXME: MH_DSYM companion file with only debug. 115 } 116 break; 117 } 118 case 0xF0: // PowerPC Windows 119 case 0x83: // Alpha 32-bit 120 case 0x84: // Alpha 64-bit 121 case 0x66: // MPS R4000 Windows 122 case 0x50: // mc68K 123 case 0x4c: // 80386 Windows 124 if (magic[1] == 0x01) 125 return COFF_FileType; 126 127 case 0x90: // PA-RISC Windows 128 case 0x68: // mc68K Windows 129 if (magic[1] == 0x02) 130 return COFF_FileType; 131 break; 132 case 0x64: // x86-64 Windows. 133 if (magic[1] == char(0x86)) 134 return COFF_FileType; 135 break; 136 137 default: 138 break; 139 } 140 return Unknown_FileType; 141 } 142 143 bool 144 Path::isArchive() const { 145 LLVMFileType type; 146 if (fs::identify_magic(str(), type)) 147 return false; 148 return type == Archive_FileType; 149 } 150 151 bool 152 Path::isDynamicLibrary() const { 153 LLVMFileType type; 154 if (fs::identify_magic(str(), type)) 155 return false; 156 switch (type) { 157 default: return false; 158 case Mach_O_FixedVirtualMemorySharedLib_FileType: 159 case Mach_O_DynamicallyLinkedSharedLib_FileType: 160 case Mach_O_DynamicallyLinkedSharedLibStub_FileType: 161 case ELF_SharedObject_FileType: 162 case COFF_FileType: return true; 163 } 164 } 165 166 bool 167 Path::isObjectFile() const { 168 LLVMFileType type; 169 if (fs::identify_magic(str(), type) || type == Unknown_FileType) 170 return false; 171 return true; 172 } 173 174 Path 175 Path::FindLibrary(std::string& name) { 176 std::vector<sys::Path> LibPaths; 177 GetSystemLibraryPaths(LibPaths); 178 for (unsigned i = 0; i < LibPaths.size(); ++i) { 179 sys::Path FullPath(LibPaths[i]); 180 FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT); 181 if (FullPath.isDynamicLibrary()) 182 return FullPath; 183 FullPath.eraseSuffix(); 184 FullPath.appendSuffix("a"); 185 if (FullPath.isArchive()) 186 return FullPath; 187 } 188 return sys::Path(); 189 } 190 191 StringRef Path::GetDLLSuffix() { 192 return &(LTDL_SHLIB_EXT[1]); 193 } 194 195 void 196 Path::appendSuffix(StringRef suffix) { 197 if (!suffix.empty()) { 198 path.append("."); 199 path.append(suffix); 200 } 201 } 202 203 bool 204 Path::isBitcodeFile() const { 205 LLVMFileType type; 206 if (fs::identify_magic(str(), type)) 207 return false; 208 return type == Bitcode_FileType; 209 } 210 211 bool Path::hasMagicNumber(StringRef Magic) const { 212 std::string actualMagic; 213 if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size()))) 214 return Magic == actualMagic; 215 return false; 216 } 217 218 static void getPathList(const char*path, std::vector<Path>& Paths) { 219 const char* at = path; 220 const char* delim = strchr(at, PathSeparator); 221 Path tmpPath; 222 while (delim != 0) { 223 std::string tmp(at, size_t(delim-at)); 224 if (tmpPath.set(tmp)) 225 if (tmpPath.canRead()) 226 Paths.push_back(tmpPath); 227 at = delim + 1; 228 delim = strchr(at, PathSeparator); 229 } 230 231 if (*at != 0) 232 if (tmpPath.set(std::string(at))) 233 if (tmpPath.canRead()) 234 Paths.push_back(tmpPath); 235 } 236 237 static StringRef getDirnameCharSep(StringRef path, const char *Sep) { 238 assert(Sep[0] != '\0' && Sep[1] == '\0' && 239 "Sep must be a 1-character string literal."); 240 if (path.empty()) 241 return "."; 242 243 // If the path is all slashes, return a single slash. 244 // Otherwise, remove all trailing slashes. 245 246 signed pos = static_cast<signed>(path.size()) - 1; 247 248 while (pos >= 0 && path[pos] == Sep[0]) 249 --pos; 250 251 if (pos < 0) 252 return path[0] == Sep[0] ? Sep : "."; 253 254 // Any slashes left? 255 signed i = 0; 256 257 while (i < pos && path[i] != Sep[0]) 258 ++i; 259 260 if (i == pos) // No slashes? Return "." 261 return "."; 262 263 // There is at least one slash left. Remove all trailing non-slashes. 264 while (pos >= 0 && path[pos] != Sep[0]) 265 --pos; 266 267 // Remove any trailing slashes. 268 while (pos >= 0 && path[pos] == Sep[0]) 269 --pos; 270 271 if (pos < 0) 272 return path[0] == Sep[0] ? Sep : "."; 273 274 return path.substr(0, pos+1); 275 } 276 277 // Include the truly platform-specific parts of this class. 278 #if defined(LLVM_ON_UNIX) 279 #include "Unix/Path.inc" 280 #endif 281 #if defined(LLVM_ON_WIN32) 282 #include "Windows/Path.inc" 283 #endif 284