diff --git a/interpreter/cling/lib/Interpreter/DynamicLibraryManagerSymbol.cpp b/interpreter/cling/lib/Interpreter/DynamicLibraryManagerSymbol.cpp index 2c71a2474d6be..785788d10f3e4 100644 --- a/interpreter/cling/lib/Interpreter/DynamicLibraryManagerSymbol.cpp +++ b/interpreter/cling/lib/Interpreter/DynamicLibraryManagerSymbol.cpp @@ -590,11 +590,14 @@ namespace cling { void HandleDynTab(const ELFFile* Elf, llvm::StringRef FileName, llvm::SmallVector& RPath, llvm::SmallVector& RunPath, - std::vector& Deps) { + std::vector& Deps, + bool& isPIEExecutable) { const char *Data = ""; if (Expected StrTabOrErr = getDynamicStrTab(Elf)) Data = StrTabOrErr.get().data(); + isPIEExecutable = false; + auto DynamicEntriesOrError = Elf->dynamicEntries(); if (!DynamicEntriesOrError) { cling::errs() << "Dyld: failed to read dynamic entries in" @@ -613,6 +616,11 @@ namespace cling { case ELF::DT_RUNPATH: SplitPaths(Data + Dyn.d_un.d_val, RunPath, utils::kAllowNonExistant, platform::kEnvDelim, false); break; + case ELF::DT_FLAGS_1: + // Check if this is not a pie executable. + if (Dyn.d_un.d_val & llvm::ELF::DF_1_PIE) + isPIEExecutable = true; + break; // (Dyn.d_tag == ELF::DT_NULL) continue; // (Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER) } @@ -731,15 +739,28 @@ namespace cling { } llvm::object::ObjectFile *BinObjF = ObjFileOrErr.get().getBinary(); if (BinObjF->isELF()) { + bool isPIEExecutable = false; + if (const auto* ELF = dyn_cast(BinObjF)) - HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps); + HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps, + isPIEExecutable); else if (const auto* ELF = dyn_cast(BinObjF)) - HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps); + HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps, + isPIEExecutable); else if (const auto* ELF = dyn_cast(BinObjF)) - HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps); + HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps, + isPIEExecutable); else if (const auto* ELF = dyn_cast(BinObjF)) - HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps); - + HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps, + isPIEExecutable); + + if ((level == 0) && isPIEExecutable) { + if (searchSystemLibraries) + m_SysLibraries.UnregisterLib(LibPath); + else + m_Libraries.UnregisterLib(LibPath); + return; + } } else if (BinObjF->isMachO()) { MachOObjectFile *Obj = (MachOObjectFile*)BinObjF; for (const auto &Command : Obj->load_commands()) { diff --git a/interpreter/cling/test/DynamicLibraryManager/call_pie.c b/interpreter/cling/test/DynamicLibraryManager/call_pie.c new file mode 100644 index 0000000000000..152c6369215aa --- /dev/null +++ b/interpreter/cling/test/DynamicLibraryManager/call_pie.c @@ -0,0 +1,17 @@ +/*------------------------------------------------------------------------------ +// 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: true +// Used as executable/library source by pie.C, etc. +CLING_EXPORT int cling_testlibrary_function() { + return 42; +} + +int main() { + return 0; +} \ No newline at end of file diff --git a/interpreter/cling/test/DynamicLibraryManager/pie.C b/interpreter/cling/test/DynamicLibraryManager/pie.C new file mode 100644 index 0000000000000..92aac5e34ac85 --- /dev/null +++ b/interpreter/cling/test/DynamicLibraryManager/pie.C @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// 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. +//------------------------------------------------------------------------------ + +// REQUIRES: not_system-windows + +// RUN: mkdir -p %t-dir/lib +// RUN: %clang -shared -DCLING_EXPORT=%dllexport %S/call_lib_A.c -o%t-dir/lib/libcall_lib_A%shlibext +// RUN: %clang -shared -DCLING_EXPORT=%dllexport %S/call_lib_B.c -o%t-dir/lib/libcall_lib_B%shlibext +// RUN: %clang %fPIC -fpie -pie -DCLING_EXPORT=%dllexport %S/call_pie.c -o%t-dir/lib/call_pie_so%shlibext +// RUN: %clang %fPIC -fpie -pie -DCLING_EXPORT=%dllexport %S/call_pie.c -o%t-dir/lib/call_pie +// RUN: cat %s | LD_LIBRARY_PATH="%t-dir/lib" %cling 2>&1 | FileCheck %s + +// Test: Cling pragma for loading libraries. Lookup and load library Lib_L_AB +// that depends on two libraries Lib_A and Lib_B via file names. +// Lib_A and Lib_B are in LD_LIBRARY_PATH. Call_pie is "PIE" compiled excutable. +// Lookup functions from libraries and use them to print result value. +// We are expecting an error for the symbol from the PIE executable, which is +// expected not to be loaded by dynamic linker. + +#pragma cling load("libcall_lib_A") +extern "C" int cling_testlibrary_function_A(); +cling_testlibrary_function_A() +// CHECK: (int) 170 + +#pragma cling load("libcall_lib_B") +extern "C" int cling_testlibrary_function_B(); +cling_testlibrary_function_B() +// CHECK: (int) 187 + +extern "C" int cling_testlibrary_function(); +cling_testlibrary_function() +// expected-error {{symbol 'cling_testlibrary_function' unresolved while linking}} + +//.q