From: Chandler Carruth Date: Thu, 22 Mar 2012 05:44:06 +0000 (+0000) Subject: Revert a series of commits to MCJIT to get the build working in CMake X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3e29671cca14f8fce1ea6b602175880cb3df7199;p=oota-llvm.git Revert a series of commits to MCJIT to get the build working in CMake (and hopefully on Windows). The bots have been down most of the day because of this, and it's not clear to me what all will be required to fix it. The commits started with r153205, then r153207, r153208, and r153221. The first commit seems to be the real culprit, but I couldn't revert a smaller number of patches. When resubmitting, r153207 and r153208 should be folded into r153205, they were simple build fixes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153241 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 3587e38ea37..8eb7590a21a 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -47,17 +47,6 @@ public: /// debugging, and may be turned on by default in debug mode. virtual void setPoisonMemory(bool poison) = 0; - /// getPointerToNamedFunction - This method returns the address of the - /// specified function by using the dlsym function call. As such it is only - /// useful for resolving library symbols, not code generated symbols. - /// - /// If AbortOnFailure is false and no function with the given name is - /// found, this function silently returns a null pointer. Otherwise, - /// it prints a message to stderr and aborts. - /// - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) = 0; - //===--------------------------------------------------------------------===// // Global Offset Table Management //===--------------------------------------------------------------------===// diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index aabfd0341ca..8ad316bc3f9 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -45,9 +45,15 @@ public: virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) = 0; - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) = 0; - + // Allocate ActualSize bytes, or more, for the named function. Return + // a pointer to the allocated memory and update Size to reflect how much + // memory was acutally allocated. + virtual uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) = 0; + + // Mark the end of the function, including how much of the allocated + // memory was actually used. + virtual void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd) = 0; }; class RuntimeDyld { diff --git a/lib/ExecutionEngine/JIT/CMakeLists.txt b/lib/ExecutionEngine/JIT/CMakeLists.txt index 52bb38970db..09728723b7d 100644 --- a/lib/ExecutionEngine/JIT/CMakeLists.txt +++ b/lib/ExecutionEngine/JIT/CMakeLists.txt @@ -2,6 +2,7 @@ add_definitions(-DENABLE_X86_JIT) add_llvm_library(LLVMJIT + Intercept.cpp JIT.cpp JITDwarfEmitter.cpp JITEmitter.cpp diff --git a/lib/ExecutionEngine/JIT/Intercept.cpp b/lib/ExecutionEngine/JIT/Intercept.cpp new file mode 100644 index 00000000000..2251a8e6b07 --- /dev/null +++ b/lib/ExecutionEngine/JIT/Intercept.cpp @@ -0,0 +1,162 @@ +//===-- Intercept.cpp - System function interception routines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// If a function call occurs to an external function, the JIT is designed to use +// the dynamic loader interface to find a function to call. This is useful for +// calling system calls and library functions that are not available in LLVM. +// Some system calls, however, need to be handled specially. For this reason, +// we intercept some of them here and use our own stubs to handle them. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Config/config.h" +using namespace llvm; + +// AtExitHandlers - List of functions to call when the program exits, +// registered with the atexit() library function. +static std::vector AtExitHandlers; + +/// runAtExitHandlers - Run any functions registered by the program's +/// calls to atexit(3), which we intercept and store in +/// AtExitHandlers. +/// +static void runAtExitHandlers() { + while (!AtExitHandlers.empty()) { + void (*Fn)() = AtExitHandlers.back(); + AtExitHandlers.pop_back(); + Fn(); + } +} + +//===----------------------------------------------------------------------===// +// Function stubs that are invoked instead of certain library calls +//===----------------------------------------------------------------------===// + +// Force the following functions to be linked in to anything that uses the +// JIT. This is a hack designed to work around the all-too-clever Glibc +// strategy of making these functions work differently when inlined vs. when +// not inlined, and hiding their real definitions in a separate archive file +// that the dynamic linker can't see. For more info, search for +// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. +#if defined(__linux__) +#if defined(HAVE_SYS_STAT_H) +#include +#endif +#include +#include +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' + * available as an exported symbol, so we have to add it explicitly. + */ +namespace { +class StatSymbols { +public: + StatSymbols() { + sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); + sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); + sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); + sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); + sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); + sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); + sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); + sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); + sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); + } +}; +} +static StatSymbols initStatSymbols; +#endif // __linux__ + +// jit_exit - Used to intercept the "exit" library call. +static void jit_exit(int Status) { + runAtExitHandlers(); // Run atexit handlers... + exit(Status); +} + +// jit_atexit - Used to intercept the "atexit" library call. +static int jit_atexit(void (*Fn)()) { + AtExitHandlers.push_back(Fn); // Take note of atexit handler... + return 0; // Always successful +} + +static int jit_noop() { + return 0; +} + +//===----------------------------------------------------------------------===// +// +/// getPointerToNamedFunction - This method returns the address of the specified +/// function by using the dynamic loader interface. As such it is only useful +/// for resolving library symbols, not code generated symbols. +/// +void *JIT::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (void*)(intptr_t)&jit_noop; + + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) return Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. +#if defined(__APPLE__) && defined(__ppc__) + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix, false)) + return Ptr; + } +#endif + } + + /// If a LazyFunctionCreator is installed, use it to get/create the function. + if (LazyFunctionCreator) + if (void *RP = LazyFunctionCreator(Name)) + return RP; + + if (AbortOnFailure) { + report_fatal_error("Program used external function '"+Name+ + "' which could not be resolved!"); + } + return 0; +} diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 16b8ee2c1f6..f715f6f3a26 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -23,7 +23,6 @@ #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetJITInfo.h" @@ -268,9 +267,9 @@ extern "C" { } JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, - JITMemoryManager *jmm, bool GVsWithCode) - : ExecutionEngine(M), TM(tm), TJI(tji), JMM(jmm), - AllocateGVsWithCode(GVsWithCode), isAlreadyCodeGenerating(false) { + JITMemoryManager *JMM, bool GVsWithCode) + : ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode), + isAlreadyCodeGenerating(false) { setTargetData(TM.getTargetData()); jitstate = new JITState(M); @@ -712,27 +711,6 @@ void *JIT::getPointerToBasicBlock(BasicBlock *BB) { } } -void *JIT::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure){ - if (!isSymbolSearchingDisabled()) { - void *ptr = JMM->getPointerToNamedFunction(Name, false); - if (ptr) - return ptr; - } - - /// If a LazyFunctionCreator is installed, use it to get/create the function. - if (LazyFunctionCreator) - if (void *RP = LazyFunctionCreator(Name)) - return RP; - - if (AbortOnFailure) { - report_fatal_error("Program used external function '"+Name+ - "' which could not be resolved!"); - } - return 0; -} - - /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index c5579815336..17d33fe8087 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -58,7 +58,6 @@ class JIT : public ExecutionEngine { TargetMachine &TM; // The current target we are compiling to TargetJITInfo &TJI; // The JITInfo for the target we are compiling to JITCodeEmitter *JCE; // JCE object - JITMemoryManager *JMM; std::vector EventListeners; /// AllocateGVsWithCode - Some applications require that global variables and diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index d404d0ccdb3..efd570d7c56 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -314,17 +314,6 @@ namespace { /// should allocate a separate slab. static const size_t DefaultSizeThreshold; - /// getPointerToNamedFunction - This method returns the address of the - /// specified function by using the dlsym function call. As such it is only - /// useful for resolving library symbols, not code generated symbols. - /// - /// If AbortOnFailure is false and no function with the given name is - /// found, this function silently returns a null pointer. Otherwise, - /// it prints a message to stderr and aborts. - /// - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); - void AllocateGOT(); // Testing methods. @@ -768,148 +757,6 @@ bool DefaultJITMemoryManager::CheckInvariants(std::string &ErrorStr) { return true; } -//===----------------------------------------------------------------------===// -// getPointerToNamedFunction() implementation. -//===----------------------------------------------------------------------===// -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Config/config.h" - -// AtExitHandlers - List of functions to call when the program exits, -// registered with the atexit() library function. -static std::vector AtExitHandlers; - -/// runAtExitHandlers - Run any functions registered by the program's -/// calls to atexit(3), which we intercept and store in -/// AtExitHandlers. -/// -static void runAtExitHandlers() { - while (!AtExitHandlers.empty()) { - void (*Fn)() = AtExitHandlers.back(); - AtExitHandlers.pop_back(); - Fn(); - } -} - -//===----------------------------------------------------------------------===// -// Function stubs that are invoked instead of certain library calls -//===----------------------------------------------------------------------===// - -// Force the following functions to be linked in to anything that uses the -// JIT. This is a hack designed to work around the all-too-clever Glibc -// strategy of making these functions work differently when inlined vs. when -// not inlined, and hiding their real definitions in a separate archive file -// that the dynamic linker can't see. For more info, search for -// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. -#if defined(__linux__) -#if defined(HAVE_SYS_STAT_H) -#include -#endif -#include -#include -/* stat functions are redirecting to __xstat with a version number. On x86-64 - * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' - * available as an exported symbol, so we have to add it explicitly. - */ -namespace { -class StatSymbols { -public: - StatSymbols() { - sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); - sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); - sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); - sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); - sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); - sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); - sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); - sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); - sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); - sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); - sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); - } -}; -} -static StatSymbols initStatSymbols; -#endif // __linux__ - -// jit_exit - Used to intercept the "exit" library call. -static void jit_exit(int Status) { - runAtExitHandlers(); // Run atexit handlers... - exit(Status); -} - -// jit_atexit - Used to intercept the "atexit" library call. -static int jit_atexit(void (*Fn)()) { - AtExitHandlers.push_back(Fn); // Take note of atexit handler... - return 0; // Always successful -} - -static int jit_noop() { - return 0; -} - -//===----------------------------------------------------------------------===// -// -/// getPointerToNamedFunction - This method returns the address of the specified -/// function by using the dynamic loader interface. As such it is only useful -/// for resolving library symbols, not code generated symbols. -/// -void *DefaultJITMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { - // Check to see if this is one of the functions we want to intercept. Note, - // we cast to intptr_t here to silence a -pedantic warning that complains - // about casting a function pointer to a normal pointer. - if (Name == "exit") return (void*)(intptr_t)&jit_exit; - if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; - - // We should not invoke parent's ctors/dtors from generated main()! - // On Mingw and Cygwin, the symbol __main is resolved to - // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors - // (and register wrong callee's dtors with atexit(3)). - // We expect ExecutionEngine::runStaticConstructorsDestructors() - // is called before ExecutionEngine::runFunctionAsMain() is called. - if (Name == "__main") return (void*)(intptr_t)&jit_noop; - - const char *NameStr = Name.c_str(); - // If this is an asm specifier, skip the sentinal. - if (NameStr[0] == 1) ++NameStr; - - // If it's an external function, look it up in the process image... - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, - // try again without the underscore. - if (NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); - if (Ptr) return Ptr; - } - - // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These - // are references to hidden visibility symbols that dlsym cannot resolve. - // If we have one of these, strip off $LDBLStub and try again. -#if defined(__APPLE__) && defined(__ppc__) - if (Name.size() > 9 && Name[Name.size()-9] == '$' && - memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { - // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. - // This mirrors logic in libSystemStubs.a. - std::string Prefix = std::string(Name.begin(), Name.end()-9); - if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) - return Ptr; - if (void *Ptr = getPointerToNamedFunction(Prefix, false)) - return Ptr; - } -#endif - - if (AbortOnFailure) { - report_fatal_error("Program used external function '"+Name+ - "' which could not be resolved!"); - } - return 0; -} - - - JITMemoryManager *JITMemoryManager::CreateDefaultMemManager() { return new DefaultJITMemoryManager(); } diff --git a/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/lib/ExecutionEngine/MCJIT/CMakeLists.txt index fef71768b49..2c0f8d65194 100644 --- a/lib/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/lib/ExecutionEngine/MCJIT/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMMCJIT MCJIT.cpp MCJITMemoryManager.cpp + Intercept.cpp ) diff --git a/lib/ExecutionEngine/MCJIT/Intercept.cpp b/lib/ExecutionEngine/MCJIT/Intercept.cpp new file mode 100644 index 00000000000..f83f4282e01 --- /dev/null +++ b/lib/ExecutionEngine/MCJIT/Intercept.cpp @@ -0,0 +1,162 @@ +//===-- Intercept.cpp - System function interception routines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// If a function call occurs to an external function, the JIT is designed to use +// the dynamic loader interface to find a function to call. This is useful for +// calling system calls and library functions that are not available in LLVM. +// Some system calls, however, need to be handled specially. For this reason, +// we intercept some of them here and use our own stubs to handle them. +// +//===----------------------------------------------------------------------===// + +#include "MCJIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Config/config.h" +using namespace llvm; + +// AtExitHandlers - List of functions to call when the program exits, +// registered with the atexit() library function. +static std::vector AtExitHandlers; + +/// runAtExitHandlers - Run any functions registered by the program's +/// calls to atexit(3), which we intercept and store in +/// AtExitHandlers. +/// +static void runAtExitHandlers() { + while (!AtExitHandlers.empty()) { + void (*Fn)() = AtExitHandlers.back(); + AtExitHandlers.pop_back(); + Fn(); + } +} + +//===----------------------------------------------------------------------===// +// Function stubs that are invoked instead of certain library calls +//===----------------------------------------------------------------------===// + +// Force the following functions to be linked in to anything that uses the +// JIT. This is a hack designed to work around the all-too-clever Glibc +// strategy of making these functions work differently when inlined vs. when +// not inlined, and hiding their real definitions in a separate archive file +// that the dynamic linker can't see. For more info, search for +// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. +#if defined(__linux__) +#if defined(HAVE_SYS_STAT_H) +#include +#endif +#include +#include +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' + * available as an exported symbol, so we have to add it explicitly. + */ +namespace { +class StatSymbols { +public: + StatSymbols() { + sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); + sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); + sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); + sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); + sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); + sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); + sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); + sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); + sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); + } +}; +} +static StatSymbols initStatSymbols; +#endif // __linux__ + +// jit_exit - Used to intercept the "exit" library call. +static void jit_exit(int Status) { + runAtExitHandlers(); // Run atexit handlers... + exit(Status); +} + +// jit_atexit - Used to intercept the "atexit" library call. +static int jit_atexit(void (*Fn)()) { + AtExitHandlers.push_back(Fn); // Take note of atexit handler... + return 0; // Always successful +} + +static int jit_noop() { + return 0; +} + +//===----------------------------------------------------------------------===// +// +/// getPointerToNamedFunction - This method returns the address of the specified +/// function by using the dynamic loader interface. As such it is only useful +/// for resolving library symbols, not code generated symbols. +/// +void *MCJIT::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (void*)(intptr_t)&jit_noop; + + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) return Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. +#if defined(__APPLE__) && defined(__ppc__) + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix, false)) + return Ptr; + } +#endif + } + + /// If a LazyFunctionCreator is installed, use it to get/create the function. + if (LazyFunctionCreator) + if (void *RP = LazyFunctionCreator(Name)) + return RP; + + if (AbortOnFailure) { + report_fatal_error("Program used external function '"+Name+ + "' which could not be resolved!"); + } + return 0; +} diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index cbb23d361dc..5f93a8d3ca8 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -215,23 +215,3 @@ GenericValue MCJIT::runFunction(Function *F, llvm_unreachable("Full-featured argument passing not supported yet!"); } - -void *MCJIT::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure){ - if (!isSymbolSearchingDisabled()) { - void *ptr = MemMgr->getPointerToNamedFunction(Name, false); - if (ptr) - return ptr; - } - - /// If a LazyFunctionCreator is installed, use it to get/create the function. - if (LazyFunctionCreator) - if (void *RP = LazyFunctionCreator(Name)) - return RP; - - if (AbortOnFailure) { - report_fatal_error("Program used external function '"+Name+ - "' which could not be resolved!"); - } - return 0; -} diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 2b3df9884eb..7f4ae77343d 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -67,7 +67,6 @@ public: /// virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); - /// mapSectionAddress - map a section to its target address space value. /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. diff --git a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h index dac8b26291f..ac8c15579ef 100644 --- a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h +++ b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h @@ -33,17 +33,46 @@ public: uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { - return JMM->allocateSpace(Size, Alignment); + return JMM->allocateDataSection(Size, Alignment, SectionID); } uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { - return JMM->allocateSpace(Size, Alignment); + return JMM->allocateCodeSection(Size, Alignment, SectionID); } - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return JMM->getPointerToNamedFunction(Name, AbortOnFailure); + // Allocate ActualSize bytes, or more, for the named function. Return + // a pointer to the allocated memory and update Size to reflect how much + // memory was acutally allocated. + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; + Function *F = M->getFunction(Name); + // Some ObjC names have a prefixed \01 in the IR. If we failed to find + // the symbol and it's of the ObjC conventions (starts with "-" or + // "+"), try prepending a \01 and see if we can find it that way. + if (!F && (Name[0] == '-' || Name[0] == '+')) + F = M->getFunction((Twine("\1") + Name).str()); + assert(F && "No matching function in JIT IR Module!"); + return JMM->startFunctionBody(F, Size); + } + + // Mark the end of the function, including how much of the allocated + // memory was actually used. + void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; + Function *F = M->getFunction(Name); + // Some ObjC names have a prefixed \01 in the IR. If we failed to find + // the symbol and it's of the ObjC conventions (starts with "-" or + // "+"), try prepending a \01 and see if we can find it that way. + if (!F && (Name[0] == '-' || Name[0] == '+')) + F = M->getFunction((Twine("\1") + Name).str()); + assert(F && "No matching function in JIT IR Module!"); + JMM->endFunctionBody(F, FunctionStart, FunctionEnd); } }; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index ff4a2c847e7..2896c2d556c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -26,290 +26,45 @@ RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { +void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress, + uint8_t *EndAddress) { + // FIXME: DEPRECATED in favor of by-section allocation. + // Allocate memory for the function via the memory manager. + uintptr_t Size = EndAddress - StartAddress + 1; + uintptr_t AllocSize = Size; + uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize); + assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) && + "Memory manager failed to allocate enough memory!"); + // Copy the function payload into the memory block. + memcpy(Mem, StartAddress, Size); + MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size); + // Remember where we put it. + unsigned SectionID = Sections.size(); + Sections.push_back(sys::MemoryBlock(Mem, Size)); + // Default the assigned address for this symbol to wherever this + // allocated it. + SymbolTable[Name] = SymbolLoc(SectionID, 0); + DEBUG(dbgs() << " allocated to [" << Mem << ", " << Mem + Size << "]\n"); +} // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { - // First, resolve relocations assotiated with external symbols. - resolveSymbols(); - // Just iterate over the sections we have and resolve all the relocations // in them. Gross overkill, but it gets the job done. for (int i = 0, e = Sections.size(); i != e; ++i) { - reassignSectionAddress(i, Sections[i].LoadAddress); + reassignSectionAddress(i, SectionLoadAddress[i]); } } void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { - for (unsigned i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Address == LocalAddress) { - reassignSectionAddress(i, TargetAddress); - return; - } - } - llvm_unreachable("Attempting to remap address of unknown section!"); -} - -bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { - // FIXME: ObjectFile don't modify MemoryBuffer. - // It should use const MemoryBuffer as parameter. - ObjectFile *obj = ObjectFile:: - createObjectFile(const_cast(InputBuffer)); - - Arch = (Triple::ArchType)obj->getArch(); - - LocalSymbolMap LocalSymbols; // Functions and data symbols from the - // object file. - ObjSectionToIDMap LocalSections; // Used sections from the object file - - error_code err; - - - // Parse symbols - DEBUG(dbgs() << "Parse symbols:\n"); - for (symbol_iterator it = obj->begin_symbols(), itEnd = obj->end_symbols(); - it != itEnd; it.increment(err)) { - if (err) break; - object::SymbolRef::Type SymType; - StringRef Name; - if ((bool)(err = it->getType(SymType))) break; - if ((bool)(err = it->getName(Name))) break; - - if (SymType == object::SymbolRef::ST_Function || - SymType == object::SymbolRef::ST_Data) { - uint64_t FileOffset; - uint32_t flags; - StringRef sData; - section_iterator sIt = obj->end_sections(); - if ((bool)(err = it->getFileOffset(FileOffset))) break; - if ((bool)(err = it->getFlags(flags))) break; - if ((bool)(err = it->getSection(sIt))) break; - if (sIt == obj->end_sections()) continue; - if ((bool)(err = sIt->getContents(sData))) break; - const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + - (uintptr_t)FileOffset; - uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); - unsigned SectionID = - findOrEmitSection(*sIt, - SymType == object::SymbolRef::ST_Function, - LocalSections); - bool isGlobal = flags & SymbolRef::SF_Global; - LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); - DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) - << " flags: " << flags - << " SID: " << SectionID - << " Offset: " << format("%p", SectOffset)); - if (isGlobal) - SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); - } - DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); - } - if (err) { - report_fatal_error(err.message()); - } - - // Parse and proccess relocations - DEBUG(dbgs() << "Parse relocations:\n"); - for (section_iterator sIt = obj->begin_sections(), - sItEnd = obj->end_sections(); sIt != sItEnd; sIt.increment(err)) { - if (err) break; - bool isFirstRelocation = true; - unsigned SectionID = 0; - StubMap Stubs; - - for (relocation_iterator it = sIt->begin_relocations(), - itEnd = sIt->end_relocations(); it != itEnd; it.increment(err)) { - if (err) break; - - // If it's first relocation in this section, find its SectionID - if (isFirstRelocation) { - SectionID = findOrEmitSection(*sIt, true, LocalSections); - DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); - isFirstRelocation = false; - } - - ObjRelocationInfo RI; - RI.SectionID = SectionID; - if ((bool)(err = it->getAdditionalInfo(RI.AdditionalInfo))) break; - if ((bool)(err = it->getOffset(RI.Offset))) break; - if ((bool)(err = it->getSymbol(RI.Symbol))) break; - if ((bool)(err = it->getType(RI.Type))) break; - - DEBUG(dbgs() << "\t\tAddend: " << RI.AdditionalInfo - << " Offset: " << format("%p", (uintptr_t)RI.Offset) - << " Type: " << (uint32_t)(RI.Type & 0xffffffffL) - << "\n"); - processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs); - } - if (err) { - report_fatal_error(err.message()); - } - } - return false; -} - -unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, - bool IsCode) { - - unsigned StubBufSize = 0, - StubSize = getMaxStubSize(); - error_code err; - if (StubSize > 0) { - for (relocation_iterator it = Section.begin_relocations(), - itEnd = Section.end_relocations(); it != itEnd; it.increment(err)) - StubBufSize += StubSize; - } - StringRef data; - uint64_t Alignment64; - if ((bool)(err = Section.getContents(data))) report_fatal_error(err.message()); - if ((bool)(err = Section.getAlignment(Alignment64))) - report_fatal_error(err.message()); - - unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; - unsigned DataSize = data.size(); - unsigned Allocate = DataSize + StubBufSize; - unsigned SectionID = Sections.size(); - const char *pData = data.data(); - uint8_t *Addr = IsCode - ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); - - memcpy(Addr, pData, DataSize); - DEBUG(dbgs() << "emitSection SectionID: " << SectionID - << " obj addr: " << format("%p", pData) - << " new addr: " << format("%p", Addr) - << " DataSize: " << DataSize - << " StubBufSize: " << StubBufSize - << " Allocate: " << Allocate - << "\n"); - Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); - return SectionID; -} - -unsigned RuntimeDyldImpl:: -findOrEmitSection(const SectionRef &Section, bool IsCode, - ObjSectionToIDMap &LocalSections) { - - unsigned SectionID = 0; - ObjSectionToIDMap::iterator sIDIt = LocalSections.find(Section); - if (sIDIt != LocalSections.end()) - SectionID = sIDIt->second; - else { - SectionID = emitSection(Section, IsCode); - LocalSections[Section] = SectionID; - } - return SectionID; -} - -void RuntimeDyldImpl::AddRelocation(const RelocationValueRef &Value, - unsigned SectionID, uintptr_t Offset, - uint32_t RelType) { - DEBUG(dbgs() << "AddRelocation SymNamePtr: " << format("%p", Value.SymbolName) - << " SID: " << Value.SectionID - << " Addend: " << format("%p", Value.Addend) - << " Offset: " << format("%p", Offset) - << " RelType: " << format("%x", RelType) - << "\n"); - - if (Value.SymbolName == 0) { - Relocations[Value.SectionID].push_back(RelocationEntry( - SectionID, - Offset, - RelType, - Value.Addend)); - } else - SymbolRelocations[Value.SymbolName].push_back(RelocationEntry( - SectionID, - Offset, - RelType, - Value.Addend)); -} - -uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { - // TODO: There is only ARM far stub now. We should add the Thumb stub, - // and stubs for branches Thumb - ARM and ARM - Thumb. - if (Arch == Triple::arm) { - uint32_t *StubAddr = (uint32_t*)Addr; - *StubAddr = 0xe51ff004; // ldr pc,