Skip to content
Snippets Groups Projects
Commit 5107c747 authored by Vivek Das Mohapatra's avatar Vivek Das Mohapatra
Browse files

Implement a capsule_shim_dlsym helper

In addition to wrapping dlopen() inside the capsule we need to
wrap dlsym() outside the capsule in order to allow libraries
that use a dlopen()/dlsym() pattern to work transparently.

capsule_shim_dlsym() bundles most of the standard logic we
expect such wrappers to use.
parent 769efa1a
No related branches found
No related tags found
1 merge request!311Build capsule-capture-libs from a bundled copy of libcapsule
......@@ -419,3 +419,38 @@ cleanup:
ld_libs_finish( &ldlibs );
return res;
}
static int
dso_is_exported (const char *dsopath, const char **exported)
{
for( const char **ex = exported; ex && *ex; ex++ )
if( soname_matches_path( *ex, dsopath ) )
return 1;
return 0;
}
void *
capsule_shim_dlsym (void *capsule,
void *handle,
const char *symbol,
const char **exported)
{
void *addr = NULL;
if( (addr = dlsym( capsule, symbol )) )
{
Dl_info dso = { 0 };
// only keep addr from the capsule if it's from an exported DSO:
// or if we are unable to determine where it came from (what?)
if( dladdr( addr, &dso ) )
if( !dso_is_exported( dso.dli_fname, exported ) )
addr = NULL;
}
if( addr == NULL )
addr = dlsym( handle, symbol );
return addr;
}
......@@ -170,3 +170,37 @@ void *capsule_shim_dlopen(Lmid_t ns,
const char **exclude,
const char *file,
int flag);
/**
* capsule_shim_dlsym:
* @capsule: A dl handle as returned by capsule_dlmopen()
* @handle: A dl handle, as passed to dlsym()
* @symbol: A symbol name, as passed to dlsym()
* @exported: An array of DSO names considered to ba valid symbol sources
*
* Returns: a void * symbol address (cf dlsym())
*
* Some libraries have a use pattern in which their caller/user
* uses dlsym() to obtain symbols rather than using those symbols
* directly in its own code (libGL is an example of this).
*
* Since the target library may have a different symbol set than the
* one the libcapsule proxy shim was generated from we can't rely on
* dlsym() finding those symbols in the shim's symbol table.
*
* Instead we must intercept dlsym() calls made outside the capsule
* and attempt to look for the required symbol in the namespace defined
* by @capsule first - If the required symbol is found there AND is
* from one of the DSO names present in @exported then that symbol is
* returned. If either of those conditions is not met then a normal
* dlsym call with the passed handle is made.
*
* This function provides the functionality described above, and is
* intended for use in a suitable wrapper implemented in the the shim
* library.
*/
void *
capsule_shim_dlsym (void *capsule,
void *handle,
const char *symbol,
const char **exported);
......@@ -29,5 +29,6 @@ man_MANS += capsule_dlmopen.3
man_MANS += capsule_init.3
man_MANS += capsule_relocate.3
man_MANS += capsule_shim_dlopen.3
man_MANS += capsule_shim_dlsym.3
CLEANFILES += $(man_MANS)
......@@ -131,3 +131,21 @@ void set_debug_flags (const char *control)
(debug_flags & DEBUG_RELOCS ) ? 'Y' : 'n' ,
(debug_flags & DEBUG_ELF ) ? 'Y' : 'n' );
}
// soname: bare libfoo.so.X style name
// path: [possibly absolute] path to DSO
// return true if soname: libFOO.so.X matches
// path: /path/to/libFOO.so.X.Y or /path/to/libFOO.so.X
int soname_matches_path (const char *soname, const char *path)
{
const char *path_soname = strrchr( path, '/' );
const char *pattern = path_soname ? path_soname + 1: path;
const size_t slen = strlen( soname );
if( strncmp( soname, pattern, slen ) != 0 )
return 0;
const char *end = pattern + slen;
return ( *end == '\0' || *end == '.' );
}
......@@ -40,3 +40,4 @@
char *safe_strncpy (char *dest, const char *src, size_t n);
int resolve_link (const char *prefix, char *path, char *dir);
int soname_matches_path (const char *soname, const char *path);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment