[Tizen 6.0] Release 2.30 version
[platform/upstream/glibc.git] / gcc-wrapper.cc
1 #include <regex>
2 #include <string>
3 #include <unistd.h>
4
5 #ifdef DEBUG
6 #include <errno.h>
7 #include <iostream>
8 #endif
9
10 const char *GCC = "/usr/bin/gcc";
11 static const int ASAN_OPTIONS_MAX = 7;
12 static const int ASAN_OPTIONS_MIN = 3;
13
14 static std::string blacklist[] = {
15     "rtld", "/dl-", "elf", "string/mem", "time/time", "time/gettimeofday",
16     "time/timegm", "time/timespec_get", "nptl/libc_pthread_init",
17     "nptl/register-atfork",
18     // In Tizen, ASan tries to write error log to procfs, in case procfs is not
19     // mounted,  this action will generate a kernel panic. So, just disable
20     // errors which happens because  of dword-aligned reading by glibc.
21     "string"};
22
23 static const char *asan_options[ASAN_OPTIONS_MAX] = {
24     "-fno-omit-frame-pointer",    "-Wno-error",         "-DSKIP_IFUNC",
25     "-fsanitize-recover=address", "-fsanitize=address", "--param",
26     "asan-use-after-return=0",
27 };
28
29 static const char *defs_option = "-Wl,-z,defs";
30 static const size_t defs_option_length = 11;
31
32 static bool AllowAsan(const char *output) {
33   if (!output)
34     return false;
35
36   std::string search_string(output);
37   if (!std::regex_match(search_string, std::regex(R"(/.*build/(.*).os$)")))
38     return false;
39
40   for (auto &b : blacklist) {
41     size_t found = search_string.find(b);
42     if (found != std::string::npos)
43       return false;
44   }
45   return true;
46 }
47
48 static const char *o(const int argc, const char **argv) {
49   for (int i = 1; i < argc; ++i) {
50     if (!argv[i])
51       break;
52     if (argv[i][0] == '-' && argv[i][1] == 'o')
53       return argv[i + 1];
54   }
55   return nullptr;
56 }
57
58 static void InitASanCommandLine(const int argc, const char **argv,
59                                 int &asan_argc, const char **&asan_argv) {
60   asan_argv = new const char *[asan_argc + 1];
61   if (!asan_argv) {
62 #ifdef DEBUG
63     std::cerr << "Can't allocate memory " << std::endl;
64 #endif
65     abort();
66   }
67   asan_argv[0] = GCC;
68   int index, asan_index;
69
70   for (asan_index = index = 1; index < argc; ++index) {
71     // Look for -Wl,-z,defs, because we don't need it
72     if (__builtin_strncmp(argv[index], defs_option, defs_option_length) == 0)
73       continue;
74     asan_argv[asan_index] = argv[index];
75     ++asan_index;
76   }
77   asan_argc = asan_index;
78 }
79
80 int main(int argc, const char **argv) {
81   if (argc == 1)
82     return 0;
83
84   const bool allow_asan = AllowAsan(o(argc, argv));
85   int options_count = allow_asan ? ASAN_OPTIONS_MAX : ASAN_OPTIONS_MIN;
86   int asan_argc = argc + options_count;
87
88   const char **asan_argv = NULL;
89   InitASanCommandLine(argc, argv, asan_argc, asan_argv);
90
91   // copy ASan options
92   __builtin_memcpy(asan_argv + asan_argc, asan_options,
93                    sizeof(char *) * options_count);
94
95   asan_argv[asan_argc + options_count] = NULL;
96   execv(GCC, (char **)asan_argv);
97 #ifdef DEBUG
98   std::cerr << "Errno: " << errno;
99 #endif
100 }
101