Build them with clang -g -O3 -flto -fsanitize=address foo.c main.c, and then run it.
The program crashes after one or two line(s) of legal input, depending on the platform.
The address sanitizer would complain something like:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2005==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000005a (pc 0x5628d989b12f bp 0x7ffe52d91d50 sp 0x7ffe52d91be0 T0)
==2005==The signal is caused by a READ memory access.
==2005==Hint: address points to the zero page.
#0 0x5628d989b12f in main /mnt/d/Store/AsanLTO/main.c:11:1
#1 0x7ff2252c3209 (/lib/x86_64-linux-gnu/libc.so.6+0x29209) (BuildId: a4c98c0c7c7803311fbd918df8fb08db852cef3d)
#2 0x7ff2252c32bb in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x292bb) (BuildId: a4c98c0c7c7803311fbd918df8fb08db852cef3d)
#3 0x5628d97dd300 in _start (/mnt/d/Store/AsanLTO/main+0x21300) (BuildId: f3e8832ba1c1f9b0111f110da8a984ab00f841b0)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /mnt/d/Store/AsanLTO/main.c:11:1 in main
==2005==ABORTING
It looks like that the crash is caused by a read instruction with a memory operand addressed through rbx register, which should have been saved/restored before/after the asm construct.
NOTE:
The crash can be always reproduced on Windows, Linux and some proprietary platforms, with clang 9.0.1, 12.0.1, 13.0.0 and 14.0.6.
The crash can also be reproduced by replacing the asm construct with any other inline assemblies with proper constraints and clobbers that writes to rbx (or its narrower variants). The actual code in our codebase is cpuid but I chose to use mov to make it clearer.
The problem disappears when you disable either LTO or ASAN, or move Foo() to the same translation unit as the caller, i.e. main.c.
Consider the following snippets:
Build them with
clang -g -O3 -flto -fsanitize=address foo.c main.c
, and then run it. The program crashes after one or two line(s) of legal input, depending on the platform. The address sanitizer would complain something like:It looks like that the crash is caused by a read instruction with a memory operand addressed through
rbx
register, which should have been saved/restored before/after theasm
construct.NOTE:
asm
construct with any other inline assemblies with proper constraints and clobbers that writes torbx
(or its narrower variants). The actual code in our codebase iscpuid
but I chose to usemov
to make it clearer.Foo()
to the same translation unit as the caller, i.e.main.c
.