LLVM API Documentation
00001 //===-- Intercept.cpp - System function interception routines -------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source 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/System/DynamicLibrary.h" 00020 #include <iostream> 00021 #include <sys/stat.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.cs.uiuc.edu/PR274. 00050 #if defined(__linux__) 00051 void *FunctionPointers[] = { 00052 (void *) stat, 00053 (void *) fstat, 00054 (void *) lstat, 00055 (void *) stat64, 00056 (void *) fstat64, 00057 (void *) lstat64, 00058 (void *) atexit, 00059 (void *) mknod 00060 }; 00061 #endif // __linux__ 00062 00063 // __mainFunc - If the program does not have a linked in __main function, allow 00064 // it to run, but print a warning. 00065 static void __mainFunc() { 00066 fprintf(stderr, "WARNING: Program called __main but was not linked to " 00067 "libcrtend.a.\nThis probably won't hurt anything unless the " 00068 "program is written in C++.\n"); 00069 } 00070 00071 // jit_exit - Used to intercept the "exit" library call. 00072 static void jit_exit(int Status) { 00073 runAtExitHandlers(); // Run atexit handlers... 00074 exit(Status); 00075 } 00076 00077 // jit_atexit - Used to intercept the "atexit" library call. 00078 static int jit_atexit(void (*Fn)(void)) { 00079 AtExitHandlers.push_back(Fn); // Take note of atexit handler... 00080 return 0; // Always successful 00081 } 00082 00083 //===----------------------------------------------------------------------===// 00084 // 00085 /// getPointerToNamedFunction - This method returns the address of the specified 00086 /// function by using the dynamic loader interface. As such it is only useful 00087 /// for resolving library symbols, not code generated symbols. 00088 /// 00089 void *JIT::getPointerToNamedFunction(const std::string &Name) { 00090 // Check to see if this is one of the functions we want to intercept... 00091 if (Name == "exit") return (void*)&jit_exit; 00092 if (Name == "atexit") return (void*)&jit_atexit; 00093 00094 // If the program does not have a linked in __main function, allow it to run, 00095 // but print a warning. 00096 if (Name == "__main") return (void*)&__mainFunc; 00097 00098 // If it's an external function, look it up in the process image... 00099 void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name); 00100 if (Ptr) return Ptr; 00101 00102 std::cerr << "ERROR: Program used external function '" << Name 00103 << "' which could not be resolved!\n"; 00104 abort(); 00105 return 0; 00106 }