Determining why gl_multithreaded() returned true currently needs gdb. This is not optimal. This patch makes this possible with less effort.
2026-05-18 Bruno Haible <[email protected]> thread-optim: Add some optional rudimentary logging. * lib/thread-optim.c (DEBUG_ELF, dbg_printf): New macros. (inspect_one_GOT): Log the return value through dbg_printf. (gl_multithreaded): Log the override through dbg_printf. diff --git a/lib/thread-optim.c b/lib/thread-optim.c index 88812307ed..ba43f16d89 100644 --- a/lib/thread-optim.c +++ b/lib/thread-optim.c @@ -22,6 +22,9 @@ /* Specification. */ #include "thread-optim.h" +/* Set to 1 to get debugging output regarding the ELF GOT inspection. */ +#define DEBUG_ELF 0 + static int mt_override = -1; void @@ -122,6 +125,13 @@ gl_set_multithreaded (bool mt) # define ElfW_2(class,type) Elf ## class ## _ ## type #endif +/* For debugging. */ +#if DEBUG_ELF +# define dbg_printf(...) fprintf (stderr, __VA_ARGS__) +#else +# define dbg_printf(...) (void)0 +#endif + #include "thread-creators.h" /* We inspect the GOT. This is more robust than inspecting the PLT, because @@ -291,8 +301,13 @@ inspect_one_GOT (struct dl_phdr_info *info, size_t size, void *data) ElfW(Word) symbol_name_offset = symtab_entry->st_name; const char *symbol_name = strtab + symbol_name_offset; if (thread_creators_lookup (symbol_name, strlen (symbol_name)) != NULL) - /* Found a jump relocation to a thread creator symbol. */ - return 1; + { + /* Found a jump relocation to a thread creator symbol. */ + dbg_printf ("gl_multithreaded() = true, because %s has the dynamic symbol %s.\n", + info->dlpi_name[0] == '\0' ? "the executable" : info->dlpi_name, + symbol_name); + return 1; + } } } @@ -370,8 +385,13 @@ inspect_one_GOT (struct dl_phdr_info *info, size_t size, void *data) abort (); const char *symbol_name = strtab + symbol_name_offset; if (thread_creators_lookup (symbol_name, strlen (symbol_name)) != NULL) - /* Found a jump relocation to a thread creator symbol. */ - return 1; + { + /* Found a jump relocation to a thread creator symbol. */ + dbg_printf ("gl_multithreaded() = true, because %s has the dynamic symbol %s.\n", + info->dlpi_name[0] == '\0' ? "the executable" : info->dlpi_name, + symbol_name); + return 1; + } } } } @@ -381,8 +401,11 @@ inspect_one_GOT (struct dl_phdr_info *info, size_t size, void *data) else { if (info->dlpi_name[0] == '\0') - /* The executable is statically linked. */ - return -1; + { + /* The executable is statically linked. */ + dbg_printf ("gl_multithreaded() = true, because the executable is statically linked.\n"); + return -1; + } } return 0; @@ -406,7 +429,11 @@ gl_multithreaded (void) { /* Consider the override. */ if (mt_override >= 0) - return mt_override; + { + dbg_printf ("gl_multithreaded() = %s, specified through gl_set_multithreaded.\n", + mt_override ? "true" : "false"); + return mt_override; + } else { /* Cache the result from is_multithreaded_uncached. */
