Path.cpp revision 1f6efa3996dd1929fbc129203ce5009b620e6969
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> 19using namespace llvm; 20using namespace sys; 21 22//===----------------------------------------------------------------------===// 23//=== WARNING: Implementation here must contain only TRULY operating system 24//=== independent code. 25//===----------------------------------------------------------------------===// 26 27bool Path::operator==(const Path &that) const { 28 return path == that.path; 29} 30 31bool Path::operator<(const Path& that) const { 32 return path < that.path; 33} 34 35Path 36Path::GetLLVMConfigDir() { 37 Path result; 38#ifdef LLVM_ETCDIR 39 if (result.set(LLVM_ETCDIR)) 40 return result; 41#endif 42 return GetLLVMDefaultConfigDir(); 43} 44 45LLVMFileType 46sys::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 141bool 142Path::isArchive() const { 143 return hasMagicNumber("!<arch>\012"); 144} 145 146bool 147Path::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 163bool 164Path::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 177Path 178Path::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 194StringRef Path::GetDLLSuffix() { 195 return &(LTDL_SHLIB_EXT[1]); 196} 197 198bool 199Path::appendSuffix(StringRef suffix) { 200 if (!suffix.empty()) { 201 std::string save(path); 202 path.append("."); 203 path.append(suffix); 204 if (!isValid()) { 205 path = save; 206 return false; 207 } 208 } 209 210 return true; 211} 212 213bool 214Path::isBitcodeFile() const { 215 std::string actualMagic; 216 if (!getMagicNumber(actualMagic, 4)) 217 return false; 218 LLVMFileType FT = 219 IdentifyFileType(actualMagic.c_str(), 220 static_cast<unsigned>(actualMagic.length())); 221 return FT == Bitcode_FileType; 222} 223 224bool Path::hasMagicNumber(StringRef Magic) const { 225 std::string actualMagic; 226 if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size()))) 227 return Magic == actualMagic; 228 return false; 229} 230 231static void getPathList(const char*path, std::vector<Path>& Paths) { 232 const char* at = path; 233 const char* delim = strchr(at, PathSeparator); 234 Path tmpPath; 235 while (delim != 0) { 236 std::string tmp(at, size_t(delim-at)); 237 if (tmpPath.set(tmp)) 238 if (tmpPath.canRead()) 239 Paths.push_back(tmpPath); 240 at = delim + 1; 241 delim = strchr(at, PathSeparator); 242 } 243 244 if (*at != 0) 245 if (tmpPath.set(std::string(at))) 246 if (tmpPath.canRead()) 247 Paths.push_back(tmpPath); 248} 249 250static StringRef getDirnameCharSep(StringRef path, const char *Sep) { 251 assert(Sep[0] != '\0' && Sep[1] == '\0' && 252 "Sep must be a 1-character string literal."); 253 if (path.empty()) 254 return "."; 255 256 // If the path is all slashes, return a single slash. 257 // Otherwise, remove all trailing slashes. 258 259 signed pos = static_cast<signed>(path.size()) - 1; 260 261 while (pos >= 0 && path[pos] == Sep[0]) 262 --pos; 263 264 if (pos < 0) 265 return path[0] == Sep[0] ? Sep : "."; 266 267 // Any slashes left? 268 signed i = 0; 269 270 while (i < pos && path[i] != Sep[0]) 271 ++i; 272 273 if (i == pos) // No slashes? Return "." 274 return "."; 275 276 // There is at least one slash left. Remove all trailing non-slashes. 277 while (pos >= 0 && path[pos] != Sep[0]) 278 --pos; 279 280 // Remove any trailing slashes. 281 while (pos >= 0 && path[pos] == Sep[0]) 282 --pos; 283 284 if (pos < 0) 285 return path[0] == Sep[0] ? Sep : "."; 286 287 return path.substr(0, pos+1); 288} 289 290// Include the truly platform-specific parts of this class. 291#if defined(LLVM_ON_UNIX) 292#include "Unix/Path.inc" 293#endif 294#if defined(LLVM_ON_WIN32) 295#include "Windows/Path.inc" 296#endif 297