[asan] Ensure __asan_register_elf_globals is called in COMDAT asan.module_ctor (... llvmorg-17.0.3
commit888437e1b60011b8a375dd30928ec925b448da57
authorFangrui Song <i@maskray.me>
Wed, 11 Oct 2023 16:23:56 +0000 (11 09:23 -0700)
committerTobias Hieta <tobias@hieta.se>
Tue, 17 Oct 2023 06:20:52 +0000 (17 08:20 +0200)
treea734880e7415871173881580fb28dd07f461a133
parent2e00f4ca4e91b02ff8e6e2d3f8e5bdd544054cb2
[asan] Ensure __asan_register_elf_globals is called in COMDAT asan.module_ctor (#67745)

On ELF platforms, when there is no global variable and the unique module ID is
non-empty, COMDAT asan.module_ctor is created with no
`__asan_register_elf_globals` calls. If this COMDAT is the prevailing copy
selected by the linker, the linkage unit will have no
`__asan_register_elf_globals` call: the redzone will not be poisoned and ODR
violation checker will not work (#67677).

This behavior is benign for -fno-sanitize-address-globals-dead-stripping because
asan.module_ctor functions that call `__asan_register_globals`
(`InstrumentGlobalsWithMetadataArray`) do not use COMDAT.

To fix #67677:

* Use COMDAT for -fsanitize-address-globals-dead-stripping on ELF platforms.
* Call `__asan_register_elf_globals` even if there is no global variable.
* If the unique module ID is empty, don't call SetComdatForGlobalMetadata:
  placing `@.str` in a COMDAT would incorrectly discard internal COMDAT `@.str`
  in other compile units.

Alternatively, when there is no global variable, asan.module_ctor is not COMDAT
and does not call `__asan_register_elf_globals`. However, the asan.module_ctor
function cannot be eliminated by the linker.

Tested the following script. Only ELF -fsanitize-address-globals-dead-stripping has changed behaviors.
```
echo > a.cc  # no global variable, empty uniqueModuleId
echo 'void f() {}' > b.cc  # with global variable, with uniqueModuleId
echo 'int g;' > c.cc  # with global variable
for t in x86_64-linux-gnu arm64-apple-macosx x86_64-windows-msvc; do
  for gc in -f{,no-}sanitize-address-globals-dead-stripping; do
    for f in a.cc b.cc c.cc; do
      echo /tmp/Rel/bin/clang -S --target=$t -fsanitize=address $gc $f -o -
      /tmp/Rel/bin/clang -S --target=$t -fsanitize=address $gc $f -o - | sed -n '/asan.module_ctor/,/ret/p'
    done
  done
done
```

---

Identical to commit 16eed8c906875e748c3cb610f3dc4b875f3882aa.
6420d3301cd4f0793adcf11f59e8398db73737d8 is an incorrect revert for genuine
purely internal issues.
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
llvm/test/Instrumentation/AddressSanitizer/basic.ll
llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll
llvm/test/Instrumentation/AddressSanitizer/global_with_comdat.ll