Allow __asan_{before, after}_dynamic_init without registered globals

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 5 05:32:18 PDT 2016


On Fri, Sep 2, 2016 at 6:06 PM, Jakub Jelinek <jakub at redhat.com> wrote:
> Hi!
>
> When optimizing, GCC optimizes away aggressively unused static globals.
> The __asan_before_dynamic_init/__asan_after_dynamic_init calls are placed
> in static constructor earlier while the registration of the globals is done
> later in the compilation process.  If all the globals with
> dynamic initialization are optimized away from some particular TU in between
> those two, libasan can fail on an assertion that dynamic_init_globals is
> empty.
>
> While I'm going to commit a GCC change which will remove the
> __asan_before_dynamic_init/__asan_after_dynamic_init in many cases when this
> happens (basically if the optimizers can prove there are no memory
> references in between the two calls), there are still testcases where such
> pair of calls is left, e.g. for
> struct S { S () { asm volatile ("" : : : "memory"); } };
> static S c;
>
> int
> main ()
> {
>   return 0;
> }
> with -O2 -fsanitize=address and ASAN_OPTIONS=check_initialization_order=true
> this still fails the assertion.  Trying to avoid this problem on the
> compiler side would decrease code quality I'm afraid, whether it is making
> sure for -fsanitize=address we keep around at least one dynamically
> initialized global if the
> __asan_before_dynamic_init/__asan_after_dynamic_init pair has been emitted,
> or adding some artificial global which would be used as the condition for
> those calls etc.
> So, can the assertion be instead just removed, this really shouldn't slow
> down the calls measurably (for __asan_before_dynamic_init it is even
> cheaper) and the assertion doesn't check something worthwhile anyway (it is
> sufficient if there is a single dynamically initialized global in any other
> TU to make it happy).
>
> Details in http://gcc.gnu.org/PR77396
>
> --- compiler-rt/lib/asan/asan_globals.cc        (revision 280486)
> +++ compiler-rt/lib/asan/asan_globals.cc        (working copy)
> @@ -368,10 +368,10 @@ void __asan_unregister_globals(__asan_gl
>  // initializer can only touch global variables in the same TU.
>  void __asan_before_dynamic_init(const char *module_name) {
>    if (!flags()->check_initialization_order ||
> -      !CanPoisonMemory())
> +      !CanPoisonMemory() ||
> +      !dynamic_init_globals)
>      return;
>    bool strict_init_order = flags()->strict_init_order;
> -  CHECK(dynamic_init_globals);
>    CHECK(module_name);
>    CHECK(asan_inited);
>    BlockingMutexLock lock(&mu_for_globals);
> @@ -394,7 +394,8 @@ void __asan_before_dynamic_init(const ch
>  // TU are poisoned.  It simply unpoisons all dynamically initialized globals.
>  void __asan_after_dynamic_init() {
>    if (!flags()->check_initialization_order ||
> -      !CanPoisonMemory())
> +      !CanPoisonMemory() ||
> +      !dynamic_init_globals)
>      return;
>    CHECK(asan_inited);
>    BlockingMutexLock lock(&mu_for_globals);


LGTM

Submitted in:
http://llvm.org/viewvc/llvm-project?view=revision&revision=280657

Thanks!


More information about the llvm-commits mailing list