Originated from BF-24901.
The same linker failure can be reproduced on non-UBSAN build variants if use dynamic_cast<IndexScanStage*> in stage_visitors.h.
The working theory is that UBSAN somehow substitutes static_cast<IndexScanStage*> with a dynamic_cast (for safety), but the latter needs vtable info of IndexScanStage, which isn't available to the linker because ix_scan.cpp is linked into query_sbe_storage lib but hash_lookup.cpp and loop_join.cpp link into query_sbe.
The problem is that query_sbe_storage already depends on query_sbe lib so the above creates a circular dependency.