https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84908
--- Comment #8 from Jason Vas Dias <jason.vas.dias at gmail dot com> --- Thanks for the clarification, and I hope the kernel developers stop compiling the mainline vDSO with -mindirect-branch=thunk-extern -mindirect-branch-register . But there are still a few things I am trying to figure out : o Why is the thunk entry reference & relocation inserted for 6 switch clauses and not for 5 ? o So do I understand correctly: __x86_indirect_thunk_rax is resolved and jumped to save %rax , jump to the address in %rcx, and then restore %rax, and return ? it is normally A) generated for libraries / executable as required or B) is in libgcc ? If (A), then what triggers it and why is it not being generated for the vDSO? If (B), then where is the code in libgcc ? I can't find it. I'd also like more details on why it is wrong to compile the vDSO with these flags - it does work, and yes causes compilation problems like this one which can be worked around by declaring all 'notrace static inline' entry points in vclock_gettime.c to have the function attributes: static inline __attribute__(( indirect_branch("keep"), function_return("keep") )) int do_monotonic_raw( int clock, struct timespec *ts ); which effectively disables the effect of -mindirect-branch=thunk-extern -mindirect-branch-register for these functions ; also __vdso_clock_gettime itself MUST be then declared: __attribute__(( indirect_branch("keep"), function_return("keep") )) int __vdso_clock_gettime ( ... ) { ... But does it cause any other issues ? I did investigate changing the switch in __vdso_clock_gettime to : #define _GTOD_LABEL_PREFIX_ _vcg_ #define _SYMCAT_(_S1_,_S2_) _S1_##_S2_ #define _GTOD_CLK_LABEL_(_CLK_) _SYMCAT_(_GTOD_LABEL_PREFIX_,_CLK_) notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts) { static const void * clk_jmp_tbl[ MAX_CLOCKS ] = { [ CLOCK_REALTIME ] = &&_GTOD_CLK_LABEL_(CLOCK_REALTIME) , [ CLOCK_MONOTONIC ] = &&_GTOD_CLK_LABEL_(CLOCK_MONOTONIC) , [ CLOCK_PROCESS_CPUTIME_ID ] = &&fallback , [ CLOCK_THREAD_CPUTIME_ID ] = &&fallback , [ CLOCK_MONOTONIC_RAW ] = &&_GTOD_CLK_LABEL_(CLOCK_MONOTONIC_RAW) , [ CLOCK_REALTIME_COARSE ] = &&_GTOD_CLK_LABEL_(CLOCK_REALTIME_COARSE) , [ CLOCK_MONOTONIC_COARSE ] = &&_GTOD_CLK_LABEL_(CLOCK_MONOTONIC_COARSE) , [ CLOCK_BOOTTIME ] = &&fallback , [ CLOCK_BOOTTIME_ALARM ] = &&fallback , [ CLOCK_SGI_CYCLE ] = &&fallback , [ CLOCK_TAI ] = &&fallback , // unused clocks [ 12 ] = &¬_supported , [ 13 ] = &¬_supported , [ 14 ] = &¬_supported , [ 15 ] = &¬_supported }; goto *clk_jmp_tbl [ clock & 0xf ] ; _GTOD_CLK_LABEL_(CLOCK_REALTIME) : if (do_realtime(ts) == VCLOCK_NONE) goto fallback; goto return_ok; _GTOD_CLK_LABEL_(CLOCK_MONOTONIC) : if (do_monotonic(ts) == VCLOCK_NONE) goto fallback; goto return_ok; _GTOD_CLK_LABEL_(CLOCK_MONOTONIC_RAW) : if (do_monotonic_raw(ts) == VCLOCK_NONE) goto fallback; goto return_ok; _GTOD_CLK_LABEL_(CLOCK_REALTIME_COARSE) : do_realtime_coarse(ts); goto return_ok; _GTOD_CLK_LABEL_(CLOCK_MONOTONIC_COARSE): do_monotonic_coarse(ts); goto return_ok; return_ok: return 0; not_supported: return -1; fallback: return vdso_fallback_gettime(clock, ts); } Results in 16 dynamic relocations, shown in objdump -R arch/x86/entry/vdso/vdso64.so.dbg output: DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 00000000000004a0 R_X86_64_RELATIVE *ABS*+0x0000000000000c49 ... 000000000000518 R_X86_64_RELATIVE *ABS*+0x0000000000000b31 what's the problem with dyn relocs ? I can't understand why GCC decides to generate relocations here - it knows all the information before hand - why can't it insert code to compute ( ( LOAD_ADDRESS_OF(__vdso_clock_gettime) == %pc at entry) + label_offset ) and populate the clk_jmp_table in an initializer in the above version of the function rather than generate relocations ? Thanks & Best Regards, Jason