The null sanitizer in UBSan adds an is-null check before each pointer dereference. As part of this, it stores and retrieves the pointer from a location on the current stack frame. Each pointer dereference uses a different location on the stack. This causes a huge increase in the frame size for functions like dump_global_stats and dump_thread_stats (127 KB and 147 KB respectively observed) which have a lot of pointer dereferences. We annotate such functions with the added annotation to disable the null sanitizer check. https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
Tried adding the annotation to various functions. The gains were highest in the first three, so added the annotation only to those. dump_global_stats: 127KB to 8B dump_local_stats: 147KB to 16B build_bb_ilist: 12.8KB to 1KB instr_encode_arch: 2.3KB to 0.5KB common_heap_alloc: 5KB to 0.7KB recreate_app_state_internal: 8.6KB to 5.1KB (The above list is based on the functions that were found to have the largest stack frame when debugging stack-overflow crashes on a proprietary app. There may be other candidates that simply weren't a problem for the specific proprietary app.)
Also fixes a pointer dereference in an assert statement that fails under the null sanitizer. This isn't a problem without the sanitizer as it only computes the offset of a member from the given pointer, but the null sanitizer checks nullness anyway and fails. This might be a bug in the sanitizer.
The null sanitizer fix is more relevant for when we want DR logs, as the major stack space savings come from the dump_*_stats functions.
Fixes: #5362