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=4 %s -o %t
5 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
6 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 9  2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
7 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 7  3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
8 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
9 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
10 // RUN: ASAN_OPTIONS=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 //
15 // CHECK-10-1: CovDump: 10 caller-callee pairs written
16 // CHECK-9-2: CovDump: 18 caller-callee pairs written
17 // CHECK-7-3: CovDump: 21 caller-callee pairs written
18 // CHECK-17-1: CovDump: 14 caller-callee pairs written
19 // CHECK-15-2: CovDump: 28 caller-callee pairs written
20 // CHECK-18-3: CovDump: 42 caller-callee pairs written
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <pthread.h>
25 int P = 0;
fFoo26 struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
fFoo127 struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo228 struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo329 struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo430 struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo531 struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo632 struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo733 struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo834 struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo935 struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1036 struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1137 struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1238 struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1339 struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1440 struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1541 struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1642 struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1743 struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1844 struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1945 struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
46 
47 Foo *foo[20] = {
48     new Foo,   new Foo1,  new Foo2,  new Foo3,  new Foo4,  new Foo5,  new Foo6,
49     new Foo7,  new Foo8,  new Foo9,  new Foo10, new Foo11, new Foo12, new Foo13,
50     new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
51 };
52 
53 int n_functions = 10;
54 int n_callers = 2;
55 
Thread(void * arg)56 void *Thread(void *arg) {
57   if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
58   if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
59   if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
60   return arg;
61 }
62 
main(int argc,char ** argv)63 int main(int argc, char **argv) {
64   if (argc >= 2)
65     n_functions = atoi(argv[1]);
66   if (argc >= 3)
67     n_callers = atoi(argv[2]);
68   const int kNumThreads = 16;
69   pthread_t t[kNumThreads];
70   for (int i = 0; i < kNumThreads; i++)
71     pthread_create(&t[i], 0, Thread, 0);
72   for (int i = 0; i < kNumThreads; i++)
73     pthread_join(t[i], 0);
74 }
75