diff options
author | Kostya Serebryany <kcc@google.com> | 2014-04-25 08:58:28 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2014-04-25 08:58:28 +0000 |
commit | e91930a7e6786e0f3fa314c66203996210ea2929 (patch) | |
tree | 0d361808759f0ca2ae3984b3962b47a58768cb3d /compiler-rt | |
parent | 56a18f02ea5fcb3f03f23cdb670b3a0412c9c89f (diff) | |
download | bcm5719-llvm-e91930a7e6786e0f3fa314c66203996210ea2929.tar.gz bcm5719-llvm-e91930a7e6786e0f3fa314c66203996210ea2929.zip |
[asan] implement an experimental detector of ODR violations. Not tested yet outside of a tiny test, may need tuning.
llvm-svn: 207210
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/asan/asan_flags.h | 1 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_globals.cc | 12 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_report.cc | 13 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_report.h | 3 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 4 | ||||
-rw-r--r-- | compiler-rt/test/asan/TestCases/Linux/odr-violation.cc | 23 |
6 files changed, 56 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_flags.h b/compiler-rt/lib/asan/asan_flags.h index 7dc78158189..3601aff461e 100644 --- a/compiler-rt/lib/asan/asan_flags.h +++ b/compiler-rt/lib/asan/asan_flags.h @@ -64,6 +64,7 @@ struct Flags { bool start_deactivated; int detect_invalid_pointer_pairs; bool detect_container_overflow; + bool detect_odr_violation; }; extern Flags asan_flags_dont_use_directly; diff --git a/compiler-rt/lib/asan/asan_globals.cc b/compiler-rt/lib/asan/asan_globals.cc index 81699676b57..8bb2e3b26ec 100644 --- a/compiler-rt/lib/asan/asan_globals.cc +++ b/compiler-rt/lib/asan/asan_globals.cc @@ -92,6 +92,18 @@ static void RegisterGlobal(const Global *g) { CHECK(AddrIsInMem(g->beg)); CHECK(AddrIsAlignedByGranularity(g->beg)); CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); + if (flags()->detect_odr_violation) { + // Try detecting ODR (One Definition Rule) violation, i.e. the situation + // where two globals with the same name are defined in different modules. + if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { + // This check may not be enough: if the first global is much larger + // the entire redzone of the second global may be within the first global. + for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { + if (g->beg == l->g->beg) + ReportODRViolation(g, l->g); + } + } + } if (flags()->poison_heap) PoisonRedZones(*g); ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index bece6eab36f..af6f7705383 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -729,6 +729,19 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack); } +void ReportODRViolation(const __asan_global *g1, const __asan_global *g2) { + ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); + Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg); + Printf("%s", d.EndWarning()); + Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name); + Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name); + Report("HINT: if you don't care about these warnings you may set " + "ASAN_OPTIONS=detect_odr_violation=0\n"); + ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name); +} + // ----------------------- CheckForInvalidPointerPair ----------- {{{1 static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) { diff --git a/compiler-rt/lib/asan/asan_report.h b/compiler-rt/lib/asan/asan_report.h index 3843a2ea2cd..1cf7c59b82d 100644 --- a/compiler-rt/lib/asan/asan_report.h +++ b/compiler-rt/lib/asan/asan_report.h @@ -54,6 +54,9 @@ void NORETURN ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid, uptr new_mid, StackTrace *stack); +void NORETURN +ReportODRViolation(const __asan_global *g1, const __asan_global *g2); + // Mac-specific errors and warnings. void WarnMacFreeUnallocated( uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack); diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 2bac66907c9..38416677239 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -225,6 +225,10 @@ static void ParseFlagsFromString(Flags *f, const char *str) { "detect_container_overflow", "If true, honor the container overflow annotations. " "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow"); + + ParseFlag(str, &f->detect_odr_violation, + "detect_odr_violation", + "If true, detect violation of One-Definition-Rule (ODR) "); } void InitializeFlags(Flags *f, const char *env) { diff --git a/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc b/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc new file mode 100644 index 00000000000..7e53e4885ca --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Linux/odr-violation.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so +// RUN: %clangxx_asan %s %t.so -Wl,-R. -o %t +// RUN: ASAN_OPTIONS=detect_odr_violation=1 not %t 2>&1 | FileCheck %s +// RUN: ASAN_OPTIONS=detect_odr_violation=0 %t 2>&1 | FileCheck %s --check-prefix=DISABLED +// RUN: %t 2>&1 | FileCheck %s --check-prefix=DISABLED + +#ifndef SZ +# define SZ 4 +#endif + +#if BUILD_SO +char G[SZ]; +#else +#include <stdio.h> +char G[100]; +int main(int argc, char **argv) { + printf("PASS: %p\n", &G); +} +#endif + +// CHECK: ERROR: AddressSanitizer: odr-violation +// CHECK: size=100 G +// DISABLED: PASS |