Skip to content

Commit 2272604

Browse files
committed
Prevent setting infinite loopback forwards
Some libraries, such as `libLAPACK` re-export their imported symbols, presumably in an effort to make it easy for users to link against just `libLAPACK` and get the BLAS symbols for free. However, when LAPACK_jll has linked against LBT as its backing BLAS library, we end up with an infinite loop, as LBT then sets its BLAS symbols to its own trampoline. This commit adds a special-case to our forwarding logic which explicitly checks for such a loop, and silently refuses to perform such a forward. This has the happy effect of filtering out direct loops, and makes it much easier to mix and match libraries that themselves depend on LBT.
1 parent b6320c1 commit 2272604

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/libblastrampoline.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,9 @@ LBT_DLLEXPORT int32_t lbt_forward(const char * libname, int32_t clear, int32_t v
355355
// Look up this symbol in the given library, if it is a valid symbol, set it!
356356
build_symbol_name(symbol_name, exported_func_names[symbol_idx], lib_suffix);
357357
void *addr = lookup_symbol(handle, symbol_name);
358-
if (addr != NULL) {
358+
void *self_symbol_addr = interface == LBT_INTERFACE_ILP64 ? exported_func64[symbol_idx] \
359+
: exported_func32[symbol_idx];
360+
if (addr != NULL && addr != self_symbol_addr) {
359361
set_forward_by_index(symbol_idx, addr, interface, complex_retstyle, f2c, verbose);
360362
BITFIELD_SET(forwards, symbol_idx);
361363
nforwards++;
@@ -443,6 +445,17 @@ __attribute__((constructor)) void init(void) {
443445
default_func = lookup_self_symbol("lbt_default_func_print_error_and_exit");
444446
}
445447

448+
// Build our lists of self-symbol addresses
449+
int32_t symbol_idx;
450+
char symbol_name[MAX_SYMBOL_LEN];
451+
for (symbol_idx=0; exported_func_names[symbol_idx] != NULL; ++symbol_idx) {
452+
exported_func32[symbol_idx] = lookup_self_symbol(exported_func_names[symbol_idx]);
453+
454+
// Look up this symbol in the given library, if it is a valid symbol, set it!
455+
build_symbol_name(symbol_name, exported_func_names[symbol_idx], "64_");
456+
exported_func64[symbol_idx] = lookup_self_symbol(symbol_name);
457+
}
458+
446459
// LBT_DEFAULT_LIBS is a semicolon-separated list of paths that should be loaded as BLAS libraries.
447460
// Each library can have a `!suffix` tacked onto the end of it, providing a library-specific
448461
// suffix_hint. Example:

src/libblastrampoline_trampdata.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,20 @@ const void ** exported_func64_addrs[] = {
3232
NULL
3333
};
3434
#undef XX
35-
#undef XX_64
35+
#undef XX_64
36+
37+
// Generate list of our own function addresses, so that we can filter
38+
// out libraries that link against us (such as LAPACK_jll) so that we
39+
// don't accidentally loop back to ourselves.
40+
#define XX(name) NULL,
41+
#define XX_64(name) NULL,
42+
const void ** exported_func32[] = {
43+
EXPORTED_FUNCS(XX)
44+
NULL
45+
};
46+
const void ** exported_func64[] = {
47+
EXPORTED_FUNCS(XX_64)
48+
NULL
49+
};
50+
#undef XX
51+
#undef XX_64

0 commit comments

Comments
 (0)