1 // Test caller-callee coverage with large number of threads
2 // and various numbers of callers and callees.
3
4 // RUN: %clangxx_asan -fsanitize-coverage=edge,indirect-calls %s -o %t
5 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
6 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 9 2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
7 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 7 3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
8 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
9 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
10 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 18 3 2>&1 | FileCheck %s --check-prefix=CHECK-18-3
11 // RUN: rm -f caller-callee*.sancov
12 //
13 // REQUIRES: asan-64-bits
14 // UNSUPPORTED: android
15 //
16 // CHECK-10-1: CovDump: 10 caller-callee pairs written
17 // CHECK-9-2: CovDump: 18 caller-callee pairs written
18 // CHECK-7-3: CovDump: 21 caller-callee pairs written
19 // CHECK-17-1: CovDump: 14 caller-callee pairs written
20 // CHECK-15-2: CovDump: 28 caller-callee pairs written
21 // CHECK-18-3: CovDump: 42 caller-callee pairs written
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <pthread.h>
26 int P = 0;
fFoo27 struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
fFoo128 struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo229 struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo330 struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo431 struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo532 struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo633 struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo734 struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo835 struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo936 struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1037 struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1138 struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1239 struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1340 struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1441 struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1542 struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1643 struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1744 struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1845 struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1946 struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
47
48 Foo *foo[20] = {
49 new Foo, new Foo1, new Foo2, new Foo3, new Foo4, new Foo5, new Foo6,
50 new Foo7, new Foo8, new Foo9, new Foo10, new Foo11, new Foo12, new Foo13,
51 new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
52 };
53
54 int n_functions = 10;
55 int n_callers = 2;
56
Thread(void * arg)57 void *Thread(void *arg) {
58 if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
59 if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
60 if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
61 return arg;
62 }
63
main(int argc,char ** argv)64 int main(int argc, char **argv) {
65 if (argc >= 2)
66 n_functions = atoi(argv[1]);
67 if (argc >= 3)
68 n_callers = atoi(argv[2]);
69 const int kNumThreads = 16;
70 pthread_t t[kNumThreads];
71 for (int i = 0; i < kNumThreads; i++)
72 pthread_create(&t[i], 0, Thread, 0);
73 for (int i = 0; i < kNumThreads; i++)
74 pthread_join(t[i], 0);
75 }
76