Re: amd64-gcc12 seems to break linker sets

From: Yuri <yuri_at_aetern.org>
Date: Sat, 05 Aug 2023 00:42:46 UTC
Yuri wrote:
> Yuri wrote:
>> I noticed that kernel built using amd64-gcc12 panics on `kldload dtraceall`:
>>
>> panic: probe defined without a provider
>> cpuid = 4
>> time = 1691186663
>> KDB: stack backtrace:
>> db_trace_self_wrapper() at db_trace_self_wrapper+0x35/frame
>> 0xfffffe00c448b8a0
>> vpanic() at vpanic+0x232/frame 0xfffffe00c448b950
>> panic() at panic+0x3c/frame 0xfffffe00c448b9b0
>> sdt_kld_load_probes() at sdt_kld_load_probes+0x346/frame 0xfffffe00c448bb70
>> sdt_load_probes_cb() at sdt_load_probes_cb+0x9/frame 0xfffffe00c448bb80
>> linker_file_foreach() at linker_file_foreach+0x53/frame 0xfffffe00c448bbc0
>> linker_load_dependencies() at linker_load_dependencies+0xe18/frame
>> 0xfffffe00c448bc70
>> link_elf_load_file() at link_elf_load_file+0x10c6/frame 0xfffffe00c448bd50
>> sys_kldload() at sys_kldload+0x820/frame 0xfffffe00c448bdf0
>> amd64_syscall() at amd64_syscall+0x11b/frame 0xfffffe00c448bf30
>> fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00c448bf30
>> --- syscall (304, FreeBSD ELF64, kldload), rip = 0x7e7e919615a, rsp =
>> 0x7e7e70ef498, rbp = 0x7e7e70efa10 ---
>>
>> Looking into it, gcc12 seems to discard the __start_set_... and
>> __stop_set_... symbols declared in sys/linker_set.h as __WEAK(), i.e.
>> __asm__(".weak ...").
>>
>> The following small test shows the problem:
>> ---
>> int
>> main(void)
>> {
>>         return (0);
>> }
>>
>> __asm__(".weak __start_set_sdt_providers_set");
>> static void const * const __set_sdt_providers_set_sym_sdt_provider_tst
>> __attribute__((__section__("set_" "sdt_providers_set")))
>> __attribute__((__used__)) = &(main);
>> __asm__(".weak __stop_set_sdt_providers_set");
>> ---
>>
>> When built using system clang:
>> ---
>> $ cc -c -o t.o t.c; nm t.o
>> 0000000000000000 r __set_sdt_providers_set_sym_sdt_provider_tst
>>                  w __start_set_sdt_providers_set
>>                  w __stop_set_sdt_providers_set
>> 0000000000000000 T main
>> ---
>>
>> When built using amd64-gcc12:
>> ---
>> $ /usr/local/bin/x86_64-unknown-freebsd14.0-gcc12 -c -o t.o t.c; nm t.o
>> 0000000000000000 r __set_sdt_providers_set_sym_sdt_provider_tst
>> 0000000000000000 T main
>> ---
>>
>> I haven't found any options to tell gcc to stop doing that; any hints?
> 
> Apparently it's any gcc version (starting with oldest available in
> ports, 4.8) and it's something that was changed in:
> ---
> commit 32231805fbe2b9438c2de50c229b43c016207a08
> Author: Greg V <greg@unrelenting.technology>
> Date:   Tue Apr 20 01:47:15 2021 +0100
> 
>     linker_set: fix globl/weak symbol redefinitions to work on clang 12
> ---
> 
> While fixing clang, it seems to broke gcc.
> 
> The following patch (reverting to previous definition for !clang) seems
> to work for both clang and gcc, dtraceall kld loads successfully, dtrace
> shows all defined std probes:
> 
> diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
> index 1de042339c3..e1d3cf636dd 100644
> --- a/sys/sys/cdefs.h
> +++ b/sys/sys/cdefs.h
> @@ -562,7 +562,11 @@
>  #endif /* __GNUC__ */
> 
>  #define        __GLOBL(sym)    __asm__(".globl " __XSTRING(sym))
> +#ifdef __clang__
>  #define        __WEAK(sym)     __asm__(".weak " __XSTRING(sym))
> +#else
> +#define        __WEAK(sym)     __GLOBL(sym)
> +#endif
> 
>  #if defined(__GNUC__)
>  #define        __IDSTRING(name,string) __asm__(".ident\t\"" string "\"")
> 

https://reviews.freebsd.org/D41329