Do not resolve symbols from executables compiled with -fPIE.
Executables that are compiled with fPIE means they are compiled in a position independent manner and are almost indistinguishable from the shared objects. A reasonably reliable way to find if this was a `pie executable` is to check the `DF_1_PIE` in the dynamic section of ELF. The pseudo-code is: ``` if DT_FLAGS_1 dynamic section entry is present if DF_1_PIE is set in DT_FLAGS_1: print pie executable else print shared object ``` See https://stackoverflow.com/questions/34519521/why-does-gcc-create-a-shared-object-instead-of-an-executable-binary-according-to/34522357#34522357 Fixes root-project/root#7366 Patch by Alexander Penev (@alexander-penev)
This commit is contained in:
parent
29d368ec6b
commit
4fa39ba82f
@ -590,11 +590,14 @@ namespace cling {
|
||||
void HandleDynTab(const ELFFile<ELFT>* Elf, llvm::StringRef FileName,
|
||||
llvm::SmallVector<llvm::StringRef,2>& RPath,
|
||||
llvm::SmallVector<llvm::StringRef,2>& RunPath,
|
||||
std::vector<StringRef>& Deps) {
|
||||
std::vector<StringRef>& Deps,
|
||||
bool& isPIEExecutable) {
|
||||
const char *Data = "";
|
||||
if (Expected<StringRef> 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()) {
|
||||
if (const auto* ELF = dyn_cast<ELF32LEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
|
||||
else if (const auto* ELF = dyn_cast<ELF32BEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
|
||||
else if (const auto* ELF = dyn_cast<ELF64LEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
|
||||
else if (const auto* ELF = dyn_cast<ELF64BEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
|
||||
bool isPIEExecutable = false;
|
||||
|
||||
if (const auto* ELF = dyn_cast<ELF32LEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
|
||||
isPIEExecutable);
|
||||
else if (const auto* ELF = dyn_cast<ELF32BEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
|
||||
isPIEExecutable);
|
||||
else if (const auto* ELF = dyn_cast<ELF64LEObjectFile>(BinObjF))
|
||||
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
|
||||
isPIEExecutable);
|
||||
else if (const auto* ELF = dyn_cast<ELF64BEObjectFile>(BinObjF))
|
||||
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()) {
|
||||
|
17
test/DynamicLibraryManager/call_pie.c
Normal file
17
test/DynamicLibraryManager/call_pie.c
Normal file
@ -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;
|
||||
}
|
39
test/DynamicLibraryManager/pie.C
Normal file
39
test/DynamicLibraryManager/pie.C
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user