From 1c19e0ab4a039c83821d10169c5f0c1877c89ba4 Mon Sep 17 00:00:00 2001 From: Frederich Munch <marsupial@users.noreply.github.com> Date: Thu, 1 Dec 2016 11:04:20 -0500 Subject: [PATCH] Fix atexit function declarations for gcc and add test. Fix mangling issues for at_quick_exit and g++ headers. --- .../cling/lib/Interpreter/Interpreter.cpp | 24 ++++++-- interpreter/cling/test/CodeUnloading/AtExit.C | 60 +++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 interpreter/cling/test/CodeUnloading/AtExit.C diff --git a/interpreter/cling/lib/Interpreter/Interpreter.cpp b/interpreter/cling/lib/Interpreter/Interpreter.cpp index bfafb83e679..f3d5c053dce 100644 --- a/interpreter/cling/lib/Interpreter/Interpreter.cpp +++ b/interpreter/cling/lib/Interpreter/Interpreter.cpp @@ -208,7 +208,13 @@ namespace cling { if (const Transaction* T = getLastTransaction()) { if (llvm::Module* M = T->getModule()) { for (const llvm::StringRef& Sym : Syms) { - if (const llvm::GlobalValue* GV = M->getNamedValue(Sym)) { + const llvm::GlobalValue* GV = M->getNamedValue(Sym); +#if defined(__GLIBCXX__) && !defined(__APPLE__) + // libstdc++ mangles at_quick_exit on Linux when headers from g++ < 5 + if (!GV && Sym.equals("at_quick_exit")) + GV = M->getNamedValue("_Z13at_quick_exitPFvvE"); +#endif + if (GV) { if (void* Addr = m_Executor->getPointerToGlobalFromJIT(*GV)) m_Executor->addSymbol(Sym.str().c_str(), Addr, true); else @@ -326,6 +332,14 @@ namespace cling { // Intercept all atexit calls, as the Interpreter and functions will be long // gone when the -native- versions invoke them. if (!SyntaxOnly) { +#if defined(__GLIBCXX__) && !defined(__APPLE__) + const char* LinkageCxx = "extern \"C++\""; + const char* Attr = LangOpts.CPlusPlus ? " throw () " : ""; +#else + const char* LinkageCxx = Linkage; + const char* Attr = ""; +#endif + // While __dso_handle is still overriden in the JIT below, // #define __dso_handle is used to mitigate the following problems: // 1. Type of __dso_handle is void* making assignemnt to it legal @@ -346,14 +360,14 @@ namespace cling { Strm << Linkage << " int __cxa_atexit(void (*f)(void*), void*, void*);\n"; // C atexit, std::atexit - Strm << Linkage << " int atexit(void(*f)()) { " - "return __cxa_atexit((void(*)(void*))f, 0, __dso_handle); }\n"; + Strm << Linkage << " int atexit(void(*f)()) " << Attr << " { return " + "__cxa_atexit((void(*)(void*))f, 0, __dso_handle); }\n"; Globals.push_back("atexit"); // C++ 11 at_quick_exit, std::at_quick_exit if (LangOpts.CPlusPlus && LangOpts.CPlusPlus11) { - Strm << Linkage << " int at_quick_exit(void(*f)()) { " - "return __cxa_atexit((void(*)(void*))f, 0, __dso_handle); }\n"; + Strm << LinkageCxx << " int at_quick_exit(void(*f)()) " << Attr << + " { return __cxa_atexit((void(*)(void*))f, 0, __dso_handle); }\n"; Globals.push_back("at_quick_exit"); } diff --git a/interpreter/cling/test/CodeUnloading/AtExit.C b/interpreter/cling/test/CodeUnloading/AtExit.C new file mode 100644 index 00000000000..8b89740e313 --- /dev/null +++ b/interpreter/cling/test/CodeUnloading/AtExit.C @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// CLING - the C++ LLVM-based InterpreterG :) +// +// This file is dual-licensed: you can choose to license it under the University +// of Illinois Open Source License or the GNU Lesser General Public License. See +// LICENSE.TXT for details. +//------------------------------------------------------------------------------ + +// RUN: cat %s | %cling -Xclang -verify 2>&1 | FileCheck %s + +// Test to check functions registered via atexit are intercepted, and __dso_handle +// is properly overridden in for child interpreters. +#include <cstdlib> +#include "cling/Interpreter/Interpreter.h" + + +static void atexit_1() { + printf("atexit_1\n"); +} +static void atexit_2() { + printf("atexit_2\n"); +} +static void atexit_3() { + printf("atexit_3\n"); +} + +atexit(atexit_1); +.undo +// Undoing the registration should call the function +// CHECK: atexit_1 + +at_quick_exit(atexit_2); +.undo +// Make sure at_quick_exit is resolved correctly (mangling issues on gcc < 5) +// CHECK-NEXT: atexit_2 + +atexit(atexit_3); + +cling::Interpreter * gChild = 0; +{ + const char* kArgV[1] = {"cling"}; + cling::Interpreter ChildInterp(*gCling, 1, kArgV); + gChild = &ChildInterp; + ChildInterp.declare("static void atexit_c() { printf(\"atexit_c %d\\n\", gChild==__dso_handle); }"); + ChildInterp.execute("atexit(atexit_c);"); +} +// ChildInterp +// CHECK-NEXT: atexit_c 1 + +static void atexit_f() { + printf("atexit_f %s\n", gCling==__dso_handle ? "true" : "false"); +} +at_quick_exit(atexit_f); + +// expected-no-diagnostics +.q + +// Reversed registration order +// CHECK-NEXT: atexit_f true +// CHECK-NEXT: atexit_3 -- GitLab