Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asan: odr-violation false alarm with shared libraries #1017

Closed
taewookoh opened this issue Nov 3, 2018 · 12 comments
Closed

asan: odr-violation false alarm with shared libraries #1017

taewookoh opened this issue Nov 3, 2018 · 12 comments

Comments

@taewookoh
Copy link

Hello,

It seems that there's a case of false odr-violation alarm with shared objects. Below is my code:

--- template.h

template<typename T>
class Base {
public:
  Base() = default;
  virtual ~Base() = default;
};

template<typename T>
class Derived : Base<T> {
public:
  Derived() = default;
  ~Derived() {};
};


--- weak.cpp

#include <iostream>
#include <typeinfo>
#include "template.h"

void weak() {
  std::cout << typeid(Derived<int>).name() << "\n";
  std::cout << typeid(Derived<char>).name() << "\n";
}

--- strong.cpp

#include <iostream>
#include <typeinfo>
#include "template.h"

template<>
class Derived<int> : Base<int> {
public:
  Derived() = default;
  ~Derived();
};

template<>
class Derived<char> : Base<char> {
public:
  Derived() = default;
  ~Derived();
};


Derived<int>::~Derived() {}
Derived<char>::~Derived() {}

void strong() {
  std::cout << typeid(Derived<int>).name() << "\n";
  std::cout << typeid(Derived<char>).name() << "\n";
}

--- main.cpp

extern void weak();
extern void strong();

int main() {
  weak();
  strong();
}

--- Makefile

CLANG=~/llvms/upstream-git/install-debug/bin/clang++

all: run

%.o: %.cpp
        $(CLANG) -fPIC -c -fsanitize=address -o $@ $^

lib%.so: %.o
        $(CLANG) -fPIC -shared -o $@ $^

main-strong: main.o libstrong.so libweak.so
        $(CLANG) -fPIC -fsanitize=address -o $@ main.o libstrong.so libweak.so -L. -lstrong -lweak

main-weak: main.o libstrong.so libweak.so
        $(CLANG) -fPIC -fsanitize=address -o $@ main.o libweak.so libstrong.so -L. -lweak -lstrong

run: main-strong main-weak
        LD_LIBRARY_PATH=. ./main-strong
        LD_LIBRARY_PATH=. ./main-weak

clean:
        rm -f *.so *.o main-strong main-weak

And below is the result from make run:

LD_LIBRARY_PATH=. ./main-strong
7DerivedIiE
7DerivedIcE
7DerivedIiE
7DerivedIcE
LD_LIBRARY_PATH=. ./main-weak
==1511755==The following global variable is not properly aligned.
==1511755==This may happen if another global with the same name
==1511755==resides in another non-instrumented module.
==1511755==Or the global comes from a C file built w/o -fno-common.
==1511755==In either case this is likely an ODR violation bug,
==1511755==but AddressSanitizer can not provide more details.
=================================================================
==1511755==ERROR: AddressSanitizer: odr-violation (0x7f91069c5249):
  [1] size=12 'typeinfo name for Derived<char>' strong.cpp
  [2] size=12 'typeinfo name for Derived<char>' strong.cpp
These globals were registered at these points:
  [1]:
    #0 0x434e17  (/data/users/twoh/tmp/weakso/main-weak+0x434e17)
    #1 0x7f91067c168b  (libstrong.so+0x168b)

  [2]:
    #0 0x434e17  (/data/users/twoh/tmp/weakso/main-weak+0x434e17)
    #1 0x7f91067c168b  (libstrong.so+0x168b)

==1511755==HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_odr_violation=0
SUMMARY: AddressSanitizer: odr-violation: global 'typeinfo name for Derived<char>' at strong.cpp
==1511755==ABORTING

If I checked the IR, _ZTS7DerivedIcE has external linkage in strong.cpp, while it has linkonce_odr linkage in weak.cpp. As ASAN doesn't instrument weak symbols, _ZTS7DerivedIcE is not aligned in libweak.so as

nm libweak.so | grep _ZTS7DerivedIcE
0000000000001249 V _ZTS7DerivedIcE

. So it seems that if dynamic linker observes weak symbol (from libweak.so) before the strong symbol (From libstrong.so) as in the case of main-weak binary, odr-violation is reported from here (https://github.com/llvm-mirror/compiler-rt/blob/master/lib/asan/asan_globals.cc#L200) when the registration is attempted from the instrumentation for the strong symbol.

I was able to repro this issue from top-of-trunk. I wonder if there's any fix or work around available. Thanks!

@taewookoh
Copy link
Author

I'm not very familiar with ASAN implementation, but what's the reason behind not instrumenting weak symbols? I wonder if we can consider just padding weak symbols to force alignment to avoid cases like this?

@yugr
Copy link

yugr commented Nov 3, 2018

@chefmax Perhaps will be fixed with indicators?

@chefmax
Copy link

chefmax commented Nov 3, 2018

@taewookoh can you try adding -mllvm -asan-use-private-alias=1 to your compilation flags?

@yugr
Copy link

yugr commented Nov 3, 2018

And export ASAN_OPTIONS=use_odr_indicator=1 before running?

@taewookoh
Copy link
Author

@yugr @chefmax Thanks for the comments! Though export ASAN_OPTIONS=use_odr_indicator=1 doesn't work, -mllvm -asan-use-private-alias=1 made the issue go away. Is there a particular reason we don't set the flag by default?

@chefmax
Copy link

chefmax commented Nov 3, 2018

@taewookoh I don't remember exact reasons, perhaps just nobody cared enough. FYI GCC uses private aliases unconditionally.
Btw, if you want more details about this issue, you can find them here: https://github.com/google/sanitizers/wiki/AddressSanitizerClangVsGCC-(6.0-vs-8.1)#feature-1

@taewookoh
Copy link
Author

@chefmax I see. Thank you!

@yugr
Copy link

yugr commented Nov 4, 2018

@kcc Any plans to enable indicators by default?

@kcc
Copy link
Contributor

kcc commented Nov 6, 2018

No plans -- nobody is working on that code currently, sorry.

@yugr
Copy link

yugr commented Nov 7, 2018

I don't think any work is needed, just flipping the default value of those two switches.

@micahsnyder
Copy link

@yugr @chefmax Thanks for the comments! Though export ASAN_OPTIONS=use_odr_indicator=1 doesn't work, -mllvm -asan-use-private-alias=1 made the issue go away. Is there a particular reason we don't set the flag by default?

I gave this an initial thumbs up because -mllvm -asan-use-private-alias=1 resolved the issue for myself on a macOS 10.14 (Mojave) VM. I never had this ODR false positive on my macOS 10.14 host.

My QA engineer reported this ODR false positive issue on his macOS 10.13 host or 10.13 and 10.14 VMs. We didn't realize until just this moment that ASAN_OPTIONS is a runtime flag for our fuzz targets, not a compile time flag (https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags). I had the QA engineer test something along the lines of ASAN_OPTIONS=use_odr_indicator=1 ./project-api-fuzzer <testcase> as well, but it didn't make any difference.

For context, we're using oss-fuzz. It's rather trivial to do validation testing with oss-fuzz's docker image and helper scripts, but the issue crops up when we build our standalone fuzz targets outside of Docker on select machines.

lmwnshn added a commit to lmwnshn/noisepage that referenced this issue Oct 14, 2020
Clang with dynamically linked ASAN misbehaves
per google/sanitizers#1017
and the workaround doesn't seem to work any more.
var-const added a commit to llvm/llvm-project that referenced this issue Feb 11, 2022
This works around a known issue in ASan. ASan doesn't instrument weak
symbols. Because instrumentation increases object size, the binary can
end up with two versions of the same object, one instrumented and one
not instrumented, with different sizes, which ASan will report as an ODR
violation. In libc++, this affects typeinfo for `std::bad_function_call`
which is emitted as a weak symbol in the test executable and as a strong
symbol in the shared library.

The main open issue for ASan appears to be
google/sanitizers#1017.

Differential Revision: https://reviews.llvm.org/D119410
ldionne pushed a commit to llvm/llvm-project that referenced this issue Feb 15, 2022
This works around a known issue in ASan. ASan doesn't instrument weak
symbols. Because instrumentation increases object size, the binary can
end up with two versions of the same object, one instrumented and one
not instrumented, with different sizes, which ASan will report as an ODR
violation. In libc++, this affects typeinfo for `std::bad_function_call`
which is emitted as a weak symbol in the test executable and as a strong
symbol in the shared library.

The main open issue for ASan appears to be
google/sanitizers#1017.

Differential Revision: https://reviews.llvm.org/D119410

(cherry picked from commit 1095397)
jfirebaugh added a commit to figma/bazel-toolchain that referenced this issue Sep 22, 2022
MaskRay added a commit to MaskRay/llvm-project that referenced this issue Nov 3, 2022
This enables odr indicators on all platforms and private aliases on non-Windows.
Note that GCC also uses private aliases: this fixes spurious
`The following global variable is not properly aligned.` errors for interposed global variables
(PR37545 (this patch should allow us to restore D46665) and
google/sanitizers#1017)

Global variables of non-hasExactDefinition() linkages (i.e.
linkonce/linkonce_odr/weak/weak_odr/common/external_weak) are not instrumented.
If an instrumented variable gets interposed to an uninstrumented variable due to
symbol interposition (e.g. in PR37545, _ZTS1A in foo.so is resolved to _ZTS1A in
the executable), there may be a bogus error.

With private aliases, the register code will not resolve to a definition in
another module, and thus prevent the issue.

google/sanitizers#398 Similar to the above, but about
an instrumented global variable gets interposed to an uninstrumented global
variable (not using address sanitizer) in another module.

Cons: negligible size increase. On ELF, this is mainly due to extra `__odr_asan_gen_*` symbols.
In relocatable files, private aliases replace some relocations referencing
global symbols with .L symbols. This may introduce some STT_SECTION symbols.

For lld, with -g0, the size increase is 0.07~0.09% for many configurations I
have tested: -O0, -O1, -O2, -O3, -O2 -ffunction-sections -fdata-sections
-Wl,--gc-sections. With -g1 or above, the size increase ratio will be even smaller.

This replaces D92078.

Don't migrate Windows for now: the static data member of a specialization
`std::num_put<char>::id` is a weak symbol, as well as its ODR indicator.
Unfortunately, link.exe (and lld without -lldmingw) generally doesn't support duplicate
weak definitions (weak symbols in different TUs likely pick different defined external symbols
and conflict).

Differential Revision: https://reviews.llvm.org/D137227
MaskRay added a commit to llvm/llvm-project that referenced this issue Nov 3, 2022
This enables odr indicators on all platforms and private aliases on non-Windows.
Note that GCC also uses private aliases: this fixes bogus
`The following global variable is not properly aligned.` errors for interposed global variables

Fix google/sanitizers#398
Fix google/sanitizers#1017
Fix #36893 (we can restore D46665)

Global variables of non-hasExactDefinition() linkages (i.e.
linkonce/linkonce_odr/weak/weak_odr/common/external_weak) are not instrumented.
If an instrumented variable gets interposed to an uninstrumented variable due to
symbol interposition (e.g. in issue 36893, _ZTS1A in foo.so is resolved to _ZTS1A in
the executable), there may be a bogus error.

With private aliases, the register code will not resolve to a definition in
another module, and thus prevent the issue.

Cons: minor size increase. This is mainly due to extra `__odr_asan_gen_*` symbols.
(ELF) In addition, in relocatable files private aliases replace some relocations
referencing global symbols with .L symbols and may introduce some STT_SECTION symbols.

For lld, with -g0, the size increase is 0.07~0.09% for many configurations I
have tested: -O0, -O1, -O2, -O3, -O2 -ffunction-sections -fdata-sections
-Wl,--gc-sections. With -g1 or above, the size increase ratio will be even smaller.

This patch obsoletes D92078.

Don't migrate Windows for now: the static data member of a specialization
`std::num_put<char>::id` is a weak symbol, as well as its ODR indicator.
Unfortunately, link.exe (and lld without -lldmingw) generally doesn't support
duplicate weak definitions (weak symbols in different TUs likely pick different
defined external symbols and conflict).

Differential Revision: https://reviews.llvm.org/D137227
@MaskRay
Copy link

MaskRay commented Nov 3, 2022

This can be closed now.

UnixJunkie pushed a commit to UnixJunkie/gromacs that referenced this issue Apr 13, 2023
In !2831 an ASAN bug relating to ODR was revealed. This is a
documented but (google/sanitizers#1017),
which both Google and GCC haveworkarounds for.
arichardson pushed a commit to CTSRD-CHERI/libcxx that referenced this issue Sep 12, 2023
This works around a known issue in ASan. ASan doesn't instrument weak
symbols. Because instrumentation increases object size, the binary can
end up with two versions of the same object, one instrumented and one
not instrumented, with different sizes, which ASan will report as an ODR
violation. In libc++, this affects typeinfo for `std::bad_function_call`
which is emitted as a weak symbol in the test executable and as a strong
symbol in the shared library.

The main open issue for ASan appears to be
google/sanitizers#1017.

Differential Revision: https://reviews.llvm.org/D119410
acelyc111 pushed a commit to apache/incubator-pegasus that referenced this issue Oct 18, 2023
#1645

This patch is to disable AddressSanitizerOneDefinitionRuleViolation, see
google/sanitizers#1017 for details.

This PR is to cherry-pick #1611 into v2.5 to solve issue #1645.
copybara-service bot pushed a commit to grpc/grpc that referenced this issue May 29, 2024
#36753 has this ASAN test failure with the following error which doesn't seem to make sense. ([full log](https://btx.cloud.google.com/invocations/a587e5cc-ca1e-46ed-a3c3-199c581583db/targets))

```
Executing tests from //test/cpp/util:grpc_tool_test@poller=epoll1
-----------------------------------------------------------------------------
=================================================================
==15==ERROR: AddressSanitizer: odr-violation (0x7fcfa2961400):
  [1] size=66 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Sliblite.so
  [2] size=66 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Slibfield_Ugenerators.so
These globals were registered at these points:
  [1]:
    #0 0x5626b4ea1488 in __asan_register_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:369:3
    #1 0x5626b4ea2559 in __asan_register_elf_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:352:3
    #2 0x7fcfa3fa4b99  (/lib64/ld-linux-x86-64.so.2+0x11b99) (BuildId: 7ae2aaae1a0e5b262df913ee0885582d2e327982)

  [2]:
    #0 0x5626b4ea1488 in __asan_register_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:369:3
    #1 0x5626b4ea2559 in __asan_register_elf_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:352:3
    #2 0x7fcfa3fa4b99  (/lib64/ld-linux-x86-64.so.2+0x11b99) (BuildId: 7ae2aaae1a0e5b262df913ee0885582d2e327982)

==15==HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_odr_violation=0
SUMMARY: AddressSanitizer: odr-violation: global 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' at external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Sliblite.so
==15==ABORTING
```

This turned out to be a known issue described at google/sanitizers#1017 and there is much to do other than disabling the ODR test. I gave a try to "-mllvm -asan-use-private-alias=1" option but it didn't change the result so I turned into this way.

Closes #36756

COPYBARA_INTEGRATE_REVIEW=#36756 from veblush:asan-workaround 622581e
PiperOrigin-RevId: 638421967
BerndDoser added a commit to BerndDoser/gromacs-ramd that referenced this issue Aug 9, 2024
sourabhsinghs pushed a commit to sourabhsinghs/grpc that referenced this issue Sep 26, 2024
grpc#36753 has this ASAN test failure with the following error which doesn't seem to make sense. ([full log](https://btx.cloud.google.com/invocations/a587e5cc-ca1e-46ed-a3c3-199c581583db/targets))

```
Executing tests from //test/cpp/util:grpc_tool_test@poller=epoll1
-----------------------------------------------------------------------------
=================================================================
==15==ERROR: AddressSanitizer: odr-violation (0x7fcfa2961400):
  [1] size=66 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Sliblite.so
  [2] size=66 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Slibfield_Ugenerators.so
These globals were registered at these points:
  [1]:
    #0 0x5626b4ea1488 in __asan_register_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:369:3
    #1 0x5626b4ea2559 in __asan_register_elf_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:352:3
    #2 0x7fcfa3fa4b99  (/lib64/ld-linux-x86-64.so.2+0x11b99) (BuildId: 7ae2aaae1a0e5b262df913ee0885582d2e327982)

  [2]:
    #0 0x5626b4ea1488 in __asan_register_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:369:3
    #1 0x5626b4ea2559 in __asan_register_elf_globals /tmp/clang-build/src/compiler-rt/lib/asan/asan_globals.cpp:352:3
    #2 0x7fcfa3fa4b99  (/lib64/ld-linux-x86-64.so.2+0x11b99) (BuildId: 7ae2aaae1a0e5b262df913ee0885582d2e327982)

==15==HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_odr_violation=0
SUMMARY: AddressSanitizer: odr-violation: global 'typeinfo name for google::protobuf::compiler::java::ImmutableExtensionLiteGenerator' at external/com_google_protobuf/src/google/protobuf/compiler/java/lite/extension.cc in /b/f/w/bazel-out/k8-fastbuild/bin/test/cpp/util/grpc_tool_test@poller=epoll1.runfiles/com_github_grpc_grpc/test/cpp/util/../../../_solib_k8/libexternal_Scom_Ugoogle_Uprotobuf_Ssrc_Sgoogle_Sprotobuf_Scompiler_Sjava_Slite_Sliblite.so
==15==ABORTING
```

This turned out to be a known issue described at google/sanitizers#1017 and there is much to do other than disabling the ODR test. I gave a try to "-mllvm -asan-use-private-alias=1" option but it didn't change the result so I turned into this way.

Closes grpc#36756

COPYBARA_INTEGRATE_REVIEW=grpc#36756 from veblush:asan-workaround 622581e
PiperOrigin-RevId: 638421967
magreenblatt added a commit to chromiumembedded/cef that referenced this issue Oct 24, 2024
These linker errors impact CEF builds but not Chromium builds due
to differences in application structure, and are becoming more
common with ongoing Chromium code refactoring.

When running via ASAN it may be necessary to set
`ASAN_OPTIONS=detect_odr_violation=0` to work around
google/sanitizers#1017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants