-
Notifications
You must be signed in to change notification settings - Fork 397
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Override dlsym instead of dlopen to correctly honour RPATH/RUNPATHS
We need to override dlopen/dlclose to account for new shared libraries being loaded in the process memory space. This is needed so we can correctly track allocations in those libraries by overriding their PLT entries and also so we can properly map the addresses of the symbols in those libraries when we resolve later native traces. Unfortunately, we can't just override dlopen directly because of the following edge case: when a shared library dlopen's another by name (e.g. dlopen("libfoo.so")), the dlopen call will honor the RPATH/RUNPATH of the calling library if it's set. Some libraries set an RPATH/RUNPATH based on $ORIGIN (the path of the calling library) to load dependencies from a relative directory based on the location of the calling library. This means that if we override dlopen, we'll end up loading the library from the wrong path or more likely, not loading it at all because the dynamic loader will think the memray extenion it's the calling library and the RPATH of the real calling library will not be honoured. To work around this, we override dlsym instead and override the symbols in the loaded libraries only the first time we have seen a handle passed to dlsym. This works because for a symbol from a given dlopen-ed library to appear in a call stack, *something* from that library has to be dlsym-ed first. The only exception to this are static initializers, but we cannot track those anyway by overriding dlopen as they run within the dlopen call itself. Signed-off-by: Pablo Galindo <[email protected]>
- Loading branch information
Showing
8 changed files
with
189 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fix a bug that was causing ``dlopen`` to not load shared libraries that have an RPATH/RUNPATH set. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include <Python.h> | ||
#include <dlfcn.h> | ||
|
||
|
||
static PyObject *hello_world(PyObject *self, PyObject *args) { | ||
// Load the shared library | ||
void *lib_handle = dlopen("sharedlib.so", RTLD_LAZY); | ||
|
||
if (!lib_handle) { | ||
PyErr_SetString(PyExc_RuntimeError, dlerror()); | ||
return NULL; | ||
} | ||
|
||
// Get the function pointer | ||
void (*my_shared_function)() = dlsym(lib_handle, "my_shared_function"); | ||
if (!my_shared_function) { | ||
PyErr_SetString(PyExc_RuntimeError, dlerror()); | ||
dlclose(lib_handle); | ||
return NULL; | ||
} | ||
|
||
// Call the function | ||
my_shared_function(); | ||
|
||
// Close the shared library | ||
dlclose(lib_handle); | ||
|
||
Py_RETURN_NONE; | ||
} | ||
|
||
static PyMethodDef methods[] = { | ||
{"hello_world", hello_world, METH_NOARGS, "Print Hello, World!"}, | ||
{NULL, NULL, 0, NULL} | ||
}; | ||
|
||
static struct PyModuleDef module = { | ||
PyModuleDef_HEAD_INIT, | ||
"ext", | ||
NULL, | ||
-1, | ||
methods | ||
}; | ||
|
||
PyMODINIT_FUNC PyInit_ext(void) { | ||
return PyModule_Create(&module); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import subprocess | ||
|
||
from setuptools import Extension | ||
from setuptools import setup | ||
from setuptools.command.build_ext import build_ext | ||
|
||
# Compile the shared library before building the extension | ||
subprocess.run( | ||
["gcc", "-shared", "-o", "sharedlibs/sharedlib.so", "sharedlibs/sharedlib.c"] | ||
) | ||
|
||
|
||
class CustomBuildExt(build_ext): | ||
def run(self): | ||
# Run the original build_ext command | ||
build_ext.run(self) | ||
|
||
# Add code to compile the shared library | ||
|
||
|
||
setup( | ||
name="ext", | ||
version="1.0", | ||
ext_modules=[ | ||
Extension( | ||
"ext", | ||
sources=["ext.c"], | ||
extra_link_args=["-Wl,-rpath,$ORIGIN/sharedlibs"], | ||
) | ||
], | ||
cmdclass={"build_ext": CustomBuildExt}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#include <stdio.h> | ||
|
||
void my_shared_function() { | ||
printf("This is a function from your_shared_lib!\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters