Commit 2ae865cb authored by Simon McVittie's avatar Simon McVittie

ldlibs: Try loading Exherbo architecture-specific ld.so cache first

I'm using Exherbo as an example of a host OS with an unusual layout that
breaks libcapsule's assumptions. Tested in an x86_64 Docker container, but
i386 is symmetrical and should also work.  This also puts the framework
in place to deal with other distributions' architecture-specific ld.so
caches.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
parent b759af73
Pipeline #16595 passed with stage
in 9 minutes and 37 seconds
......@@ -271,7 +271,7 @@ _capsule_load (const capsule cap,
// ==================================================================
// read in the ldo.so.cache - this will contain all architectures
// currently installed (x86_64, i386, x32) in no particular order
if( ld_libs_load_cache( &ldlibs, "/etc/ld.so.cache", errcode, error ) )
if( ld_libs_load_cache( &ldlibs, errcode, error ) )
{
if( debug_flags & DEBUG_LDCACHE )
dump_ld_cache( &ldlibs );
......
......@@ -221,7 +221,7 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
goto cleanup;
}
if( !ld_libs_load_cache( &ldlibs, "/etc/ld.so.cache", &code, &errors ) )
if( !ld_libs_load_cache( &ldlibs, &code, &errors ) )
{
DEBUG( DEBUG_LDCACHE|DEBUG_WRAPPERS|DEBUG_DLFUNC,
"Loading ld.so.cache from %s: error %d: %s", cap->ns->prefix,
......
......@@ -319,7 +319,7 @@ init_with_target( ld_libs *ldlibs, const char *tree, const char *target,
goto fail;
}
if( !ld_libs_load_cache( ldlibs, "/etc/ld.so.cache", code, message ) )
if( !ld_libs_load_cache( ldlibs, code, message ) )
{
goto fail;
}
......@@ -668,7 +668,6 @@ static bool
capture_soname_match( const char *pattern, const capture_options *options,
int *code, char **message )
{
_capsule_autofree char *cache_path = NULL;
cache_foreach_context ctx = {
.pattern = pattern,
.options = options,
......@@ -678,13 +677,28 @@ capture_soname_match( const char *pattern, const capture_options *options,
.message = message,
};
bool ret = false;
size_t i;
DEBUG( DEBUG_TOOL, "%s", pattern );
cache_path = build_filename_alloc( option_provider, "/etc/ld.so.cache",
NULL );
for( i = 0; ld_cache_filenames[i] != NULL; i++ )
{
_capsule_autofree char *cache_path = NULL;
if( message != NULL )
_capsule_clear( message );
cache_path = build_filename_alloc( option_provider,
ld_cache_filenames[i],
NULL );
if( ld_cache_open( &ctx.cache, cache_path, code, message ) )
break;
else
assert( !ctx.cache.is_open );
}
if( !ld_cache_open( &ctx.cache, cache_path, code, message ) )
if( !ctx.cache.is_open )
goto out;
if( ld_cache_foreach( &ctx.cache, cache_foreach_cb, &ctx ) != 0 )
......
......@@ -76,6 +76,19 @@ static const char *const abi_tag_os[] =
// end of stolen header structures
////////////////////////////////////////////////////////////////////////////
const char * const ld_cache_filenames[] =
{
#ifdef __i386__
"/etc/ld-i686-pc-linux-gnu.cache", /* Exherbo */
#endif
#ifdef __x86_64__
"/etc/ld-x86_64-pc-linux-gnu.cache", /* Exherbo */
#endif
"/etc/ld.so.cache", /* interoperable */
NULL
};
static void
ld_cache_reset (ld_cache *cache)
{
......
......@@ -85,6 +85,8 @@ typedef struct
// ==========================================================================
extern const char * const ld_cache_filenames[];
typedef intptr_t (*ld_cache_entry_cb) (const char *name,
int flag,
unsigned int osv,
......
......@@ -448,7 +448,7 @@ search_ldcache (const char *name, ld_libs *ldlibs, int i)
if( !ldlibs->ldcache.is_open )
{
if( !ld_libs_load_cache( ldlibs, "/etc/ld.so.cache", NULL, NULL ) )
if( !ld_libs_load_cache( ldlibs, NULL, NULL ) )
{
// TODO: report error?
return 0;
......@@ -1128,21 +1128,29 @@ stat_caller (void)
//
// this function respects any path prefix specified in ldlibs
int
ld_libs_load_cache (ld_libs *libs, const char *path, int *code, char **message)
ld_libs_load_cache (ld_libs *libs, int *code, char **message)
{
char prefixed[PATH_MAX] = { '\0' };
int rv;
size_t i;
if( build_filename( prefixed, sizeof(prefixed), libs->prefix.path,
path, NULL ) >= sizeof(prefixed) )
for( i = 0; ld_cache_filenames[i] != NULL; i++ )
{
_capsule_set_error( code, message, ENAMETOOLONG,
"Cannot append \"%s\" to prefix \"%s\": too long",
path, libs->prefix.path );
return 0;
}
if( message != NULL )
_capsule_clear( message );
rv = ld_cache_open( &libs->ldcache, prefixed, code, message );
if( build_filename( prefixed, sizeof(prefixed), libs->prefix.path,
ld_cache_filenames[i], NULL ) >= sizeof(prefixed) )
{
_capsule_set_error( code, message, ENAMETOOLONG,
"Cannot append \"%s\" to prefix \"%s\": too long",
ld_cache_filenames[i], libs->prefix.path );
continue;
}
return rv;
if( ld_cache_open( &libs->ldcache, prefixed, code, message ) )
return 1;
}
// return the last error
return 0;
}
......@@ -103,8 +103,7 @@ int ld_libs_set_target (ld_libs *ldlibs, const char *target,
int *code, char **message);
int ld_libs_find_dependencies (ld_libs *ldlibs, int *code, char **message);
void ld_libs_finish (ld_libs *ldlibs);
int ld_libs_load_cache (ld_libs *libs, const char *path, int *code,
char **message);
int ld_libs_load_cache (ld_libs *libs, int *code, char **message);
void *ld_libs_load (ld_libs *ldlibs, Lmid_t *namespace, int flag, int *error,
char **message);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment