Skip to content

Commit a257639

Browse files
committed
[asan] Don't check ODR violations for particular types of globals
Summary: private and internal: should not trigger ODR at all. unnamed_addr: current ODR checking approach fail and rereport false violation if a linker merges such globals linkonce_odr, weak_odr: could cause similar problems and they are already not instrumented for ELF. Reviewers: eugenis, kcc Subscribers: kubamracek, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D55621 llvm-svn: 349015
1 parent 577b9fc commit a257639

File tree

9 files changed

+89
-9
lines changed

9 files changed

+89
-9
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,ALIAS1
2+
3+
// No alias on Windows but indicators should work.
4+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefixes=CHECK,ALIAS0
5+
6+
static int global;
7+
8+
int main() {
9+
return global;
10+
}
11+
12+
// CHECK-NOT: __odr_asan_gen
13+
// CHECK-NOT: private alias
14+
// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [60 x i8] } zeroinitializer, align 32
15+
// CHECK: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 -1 }]
16+
// CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
17+
// CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)

compiler-rt/lib/asan/asan_globals.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
8383
}
8484

8585
static void ReportGlobal(const Global &g, const char *prefix) {
86-
Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
87-
prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
88-
g.module_name, g.has_dynamic_init);
86+
Report(
87+
"%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu "
88+
"odr_indicator=%p\n",
89+
prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
90+
g.module_name, g.has_dynamic_init, (void *)g.odr_indicator);
8991
if (g.location) {
9092
Report(" location (%p): name=%s[%p], %d %d\n", g.location,
9193
g.location->filename, g.location->filename, g.location->line_no,
@@ -133,6 +135,9 @@ enum GlobalSymbolState {
133135
// this method in case compiler instruments global variables through their
134136
// local aliases.
135137
static void CheckODRViolationViaIndicator(const Global *g) {
138+
// Instrumentation requests to skip ODR check.
139+
if (g->odr_indicator == UINTPTR_MAX)
140+
return;
136141
u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
137142
if (*odr_indicator == UNREGISTERED) {
138143
*odr_indicator = REGISTERED;
@@ -246,7 +251,7 @@ static void UnregisterGlobal(const Global *g) {
246251
// implementation. It might not be worth doing anyway.
247252

248253
// Release ODR indicator.
249-
if (UseODRIndicator(g)) {
254+
if (UseODRIndicator(g) && g->odr_indicator != UINTPTR_MAX) {
250255
u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
251256
*odr_indicator = UNREGISTERED;
252257
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clangxx_asan -fPIC %s -o %t
2+
// RUN: %env_asan_opts=report_globals=2 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,INDICATOR0
3+
4+
// RUN: %clangxx_asan -fsanitize-address-use-odr-indicator -fPIC %s -o %t
5+
// RUN: %env_asan_opts=report_globals=2 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,INDICATOR1
6+
7+
#include <stdio.h>
8+
9+
int test_global_1;
10+
// INDICATOR0-DAG: Added Global{{.*}} name=test_global_1{{.*}} odr_indicator={{0x0+$}}
11+
// INDICATOR1-DAG: Added Global{{.*}} name=test_global_1{{.*}} odr_indicator={{0x0*[^0]+.*$}}
12+
13+
static int test_global_2;
14+
// CHECK-DAG: Added Global{{.*}} name=test_global_2{{.*}} odr_indicator={{0xf+$}}
15+
16+
namespace {
17+
static int test_global_3;
18+
// CHECK-DAG: Added Global{{.*}} name={{.*}}::test_global_3{{.*}} odr_indicator={{0xf+$}}
19+
} // namespace
20+
21+
int main() {
22+
const char f[] = "%d %d %d\n";
23+
// CHECK-DAG: Added Global{{.*}} name=__const.main.f{{.*}} odr_indicator={{0xf+$}}
24+
printf(f, test_global_1, test_global_2, test_global_3);
25+
return 0;
26+
}

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2190,7 +2190,13 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M, bool
21902190
GlobalAlias::create(GlobalValue::PrivateLinkage, "", NewGlobal);
21912191
}
21922192

2193-
if (UseOdrIndicator) {
2193+
// ODR check is not useful for the following, but we see false reports
2194+
// caused by linker optimizations.
2195+
if (NewGlobal->hasLocalLinkage() || NewGlobal->hasGlobalUnnamedAddr() ||
2196+
NewGlobal->hasLinkOnceODRLinkage() || NewGlobal->hasWeakODRLinkage()) {
2197+
ODRIndicator = ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, -1),
2198+
IRB.getInt8PtrTy());
2199+
} else if (UseOdrIndicator) {
21942200
// With local aliases, we need to provide another externally visible
21952201
// symbol __odr_asan_XXX to detect ODR violation.
21962202
auto *ODRIndicatorSym =

llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
55
target triple = "x86_64-unknown-linux-gnu"
66
; no action should be taken for these globals
77
@global_noinst = linkonce_odr constant [2 x i8] [i8 1, i8 2]
8+
@global_weak_noinst = weak_odr constant [2 x i8] [i8 1, i8 2]
89
@global_inst = private constant [2 x i8] [i8 1, i8 2]
910
; CHECK-NOT: {{asan_gen.*global_noinst}}
11+
; CHECK-NOT: {{asan_gen.*global_weak_noinst}}
1012
; CHECK: {{asan_gen.*global_inst}}
1113
; CHECK: @asan.module_ctor

llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ target triple = "x86_64-unknown-linux-gnu"
2222
; CHECK: [[FILENAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [22 x i8] c"/tmp/asan-globals.cpp\00", align 1
2323
; CHECK: [[LOCDESCR:@___asan_gen_.[0-9]+]] = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* [[FILENAME]], i32 5, i32 5 }
2424
; CHECK: @__asan_global_global = {{.*}}i64 ptrtoint ({ i32, [60 x i8] }* @global to i64){{.*}} section "asan_globals"{{.*}}, !associated
25-
; CHECK: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [50 x i8] }* @.str to i64){{.*}} section "asan_globals"{{.*}}, !associated
25+
; CHECK: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [50 x i8] }* @{{.str|1}} to i64){{.*}} section "asan_globals"{{.*}}, !associated
2626

2727
; The metadata has to be inserted to llvm.compiler.used to avoid being stripped
2828
; during LTO.

llvm/test/Instrumentation/AddressSanitizer/local_alias.ll

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@
66
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
77
target triple = "x86_64-unknown-linux-gnu"
88

9-
@a = internal global [2 x i32] zeroinitializer, align 4
9+
@a = dso_local global [2 x i32] zeroinitializer, align 4
10+
@b = private global [2 x i32] zeroinitializer, align 4
11+
@c = internal global [2 x i32] zeroinitializer, align 4
12+
@d = unnamed_addr global [2 x i32] zeroinitializer, align 4
1013

1114
; Check that we generate internal alias and odr indicator symbols for global to be protected.
1215
; CHECK-NOINDICATOR-NOT: __odr_asan_gen_a
1316
; CHECK-NOALIAS-NOT: private alias
14-
; CHECK-INDICATOR: @__odr_asan_gen_a = internal global i8 0, align 1
17+
; CHECK-INDICATOR: @__odr_asan_gen_a = global i8 0, align 1
1518
; CHECK-ALIAS: @0 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @a
1619

20+
; CHECK-ALIAS: @1 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @b
21+
; CHECK-ALIAS: @2 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @c
22+
; CHECK-ALIAS: @3 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @d
23+
1724
; Function Attrs: nounwind sanitize_address uwtable
1825
define i32 @foo(i32 %M) #0 {
1926
entry:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt < %s -asan -asan-module -S | FileCheck %s
2+
3+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "x86_64-unknown-linux-gnu"
5+
6+
@a = global [2 x i32] zeroinitializer, align 4
7+
@b = private global [2 x i32] zeroinitializer, align 4
8+
@c = internal global [2 x i32] zeroinitializer, align 4
9+
@d = unnamed_addr global [2 x i32] zeroinitializer, align 4
10+
11+
; CHECK: @__asan_global_a = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @a to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.1 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 0 }
12+
13+
; CHECK: @__asan_global_b = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @b to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.2 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 }
14+
15+
; CHECK: @__asan_global_c = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @c to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.3 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 }
16+
17+
; CHECK: @__asan_global_d = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @d to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.4 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 }

llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
; CHECK-SAME: { i64 ptrtoint ({ [5 x i8], [59 x i8] }* @"??_C@_04JIHMPGLA@asdf?$AA@" to i64),
1616
; CHECK-SAME: i64 5, i64 64, i64 ptrtoint ([17 x i8]* @___asan_gen_.1 to i64),
1717
; CHECK-SAME: i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0,
18-
; CHECK-SAME: i64 ptrtoint ({ [6 x i8]*, i32, i32 }* @___asan_gen_.3 to i64), i64 0 },
18+
; CHECK-SAME: i64 ptrtoint ({ [6 x i8]*, i32, i32 }* @___asan_gen_.3 to i64), i64 -1 },
1919
; CHECK-SAME: section ".ASAN$GL", comdat($"??_C@_04JIHMPGLA@asdf?$AA@"), align 64
2020

2121
; ModuleID = 't.cpp'

0 commit comments

Comments
 (0)