LLVM API Documentation

Path.cpp

Go to the documentation of this file.
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.