Skip to content

Commit

Permalink
Do not resolve symbols from executables compiled with -fPIE.
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
vgvassilev authored and jenkins committed Jan 7, 2022
1 parent 29d368e commit 4fa39ba
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
33 changes: 27 additions & 6 deletions lib/Interpreter/DynamicLibraryManagerSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
}
Expand Down Expand Up @@ -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<ELF32LEObjectFile>(BinObjF))
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
isPIEExecutable);
else if (const auto* ELF = dyn_cast<ELF32BEObjectFile>(BinObjF))
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
isPIEExecutable);
else if (const auto* ELF = dyn_cast<ELF64LEObjectFile>(BinObjF))
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps);
HandleDynTab(ELF->getELFFile(), FileName, RPath, RunPath, Deps,
isPIEExecutable);
else if (const auto* ELF = dyn_cast<ELF64BEObjectFile>(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()) {
Expand Down
17 changes: 17 additions & 0 deletions test/DynamicLibraryManager/call_pie.c
Original file line number Diff line number Diff line change
@@ -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 changes: 39 additions & 0 deletions test/DynamicLibraryManager/pie.C
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4fa39ba

Please sign in to comment.