LLVM API Documentation
00001 //===-- Intercept.cpp - System function interception routines -------------===// 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 // If a function call occurs to an external function, the JIT is designed to use 00011 // the dynamic loader interface to find a function to call. This is useful for 00012 // calling system calls and library functions that are not available in LLVM. 00013 // Some system calls, however, need to be handled specially. For this reason, 00014 // we intercept some of them here and use our own stubs to handle them. 00015 // 00016 //===----------------------------------------------------------------------===// 00017 00018 #include "JIT.h" 00019 #include "llvm/Support/Streams.h" 00020 #include "llvm/System/DynamicLibrary.h" 00021 #include "llvm/Config/config.h" 00022 using namespace llvm; 00023 00024 // AtExitHandlers - List of functions to call when the program exits, 00025 // registered with the atexit() library function. 00026 static std::vector<void (*)()> AtExitHandlers; 00027 00028 /// runAtExitHandlers - Run any functions registered by the program's 00029 /// calls to atexit(3), which we intercept and store in 00030 /// AtExitHandlers. 00031 /// 00032 static void runAtExitHandlers() { 00033 while (!AtExitHandlers.empty()) { 00034 void (*Fn)() = AtExitHandlers.back(); 00035 AtExitHandlers.pop_back(); 00036 Fn(); 00037 } 00038 } 00039 00040 //===----------------------------------------------------------------------===// 00041 // Function stubs that are invoked instead of certain library calls 00042 //===----------------------------------------------------------------------===// 00043 00044 // Force the following functions to be linked in to anything that uses the 00045 // JIT. This is a hack designed to work around the all-too-clever Glibc 00046 // strategy of making these functions work differently when inlined vs. when 00047 // not inlined, and hiding their real definitions in a separate archive file 00048 // that the dynamic linker can't see. For more info, search for 00049 // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. 00050 #if defined(__linux__) 00051 #if defined(HAVE_SYS_STAT_H) 00052 #include <sys/stat.h> 00053 #endif 00054 00055 /* stat functions are redirecting to __xstat with a version number. On x86-64 00056 * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' 00057 * available as an exported symbol, so we have to add it explicitly. 00058 */ 00059 class StatSymbols { 00060 public: 00061 StatSymbols() { 00062 sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); 00063 sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); 00064 sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); 00065 sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); 00066 sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); 00067 sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); 00068 sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); 00069 sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); 00070 } 00071 }; 00072 static StatSymbols initStatSymbols; 00073 #endif // __linux__ 00074 00075 // jit_exit - Used to intercept the "exit" library call. 00076 static void jit_exit(int Status) { 00077 runAtExitHandlers(); // Run atexit handlers... 00078 exit(Status); 00079 } 00080 00081 // jit_atexit - Used to intercept the "atexit" library call. 00082 static int jit_atexit(void (*Fn)(void)) { 00083 AtExitHandlers.push_back(Fn); // Take note of atexit handler... 00084 return 0; // Always successful 00085 } 00086 00087 //===----------------------------------------------------------------------===// 00088 // 00089 /// getPointerToNamedFunction - This method returns the address of the specified 00090 /// function by using the dynamic loader interface. As such it is only useful 00091 /// for resolving library symbols, not code generated symbols. 00092 /// 00093 void *JIT::getPointerToNamedFunction(const std::string &Name, 00094 bool AbortOnFailure) { 00095 if (!isSymbolSearchingDisabled()) { 00096 // Check to see if this is one of the functions we want to intercept. Note, 00097 // we cast to intptr_t here to silence a -pedantic warning that complains 00098 // about casting a function pointer to a normal pointer. 00099 if (Name == "exit") return (void*)(intptr_t)&jit_exit; 00100 if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; 00101 00102 const char *NameStr = Name.c_str(); 00103 // If this is an asm specifier, skip the sentinal. 00104 if (NameStr[0] == 1) ++NameStr; 00105 00106 // If it's an external function, look it up in the process image... 00107 void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); 00108 if (Ptr) return Ptr; 00109 00110 // If it wasn't found and if it starts with an underscore ('_') character, 00111 // and has an asm specifier, try again without the underscore. 00112 if (Name[0] == 1 && NameStr[0] == '_') { 00113 Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); 00114 if (Ptr) return Ptr; 00115 } 00116 00117 // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These 00118 // are references to hidden visibility symbols that dlsym cannot resolve. 00119 // If we have one of these, strip off $LDBLStub and try again. 00120 #if defined(__APPLE__) && defined(__ppc__) 00121 if (Name.size() > 9 && Name[Name.size()-9] == '$' && 00122 memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { 00123 // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. 00124 // This mirrors logic in libSystemStubs.a. 00125 std::string Prefix = std::string(Name.begin(), Name.end()-9); 00126 if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) 00127 return Ptr; 00128 if (void *Ptr = getPointerToNamedFunction(Prefix, false)) 00129 return Ptr; 00130 } 00131 #endif 00132 } 00133 00134 /// If a LazyFunctionCreator is installed, use it to get/create the function. 00135 if (LazyFunctionCreator) 00136 if (void *RP = LazyFunctionCreator(Name)) 00137 return RP; 00138 00139 if (AbortOnFailure) { 00140 cerr << "ERROR: Program used external function '" << Name 00141 << "' which could not be resolved!\n"; 00142 abort(); 00143 } 00144 return 0; 00145 }