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