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