GN: add sanitize arg

Attempt to take over all *SAN builds.

MSAN has a lot of coordination required between gn/BUILD.gn and gn_flavor.py.
I'd like to follow up to move more of this into gn/BUILD.gn, to make it easier
to use locally.

The compile steps should be much faster now.  We no longer build CMake
and Clang for every run, instead using the clang_linux CIPD package.  This
removes the need for all the third_party/externals/llvm/... dependencies.

Similarly, since we're using the clang_linux package, we no longer depend
on Chrome's Clang, and thus no longer need to sync chromium on these bots.

Instead of packaging up MSAN libraries and llvm-symbolizer in the compile
output, I have the test / perf bots also depend on the clang_linux package.
These do not vary from build to build.

No more need for the xsan.blacklist -include hack: Clang, GN, and Ninja
all track changes to xsan.blacklist without our help.

This has the incidental effect of upgrading the compiler used by *SAN
bots from Clang 3.8 to Clang 3.9.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2289343002

Review-Url: https://codereview.chromium.org/2289343002
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index a076aa9..c5db0a9 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -23,7 +23,9 @@
 }
 
 config("no_rtti") {
-  cflags_cc = [ "-fno-rtti" ]
+  if (sanitize != "ASAN") {  # -fsanitize=vptr requires RTTI
+    cflags_cc = [ "-fno-rtti" ]
+  }
 }
 
 config("default") {
@@ -53,6 +55,8 @@
 
     "-Wnon-virtual-dtor",
   ]
+  ldflags = []
+
   if (current_cpu == "arm") {
     cflags += [
       "-march=armv7-a",
@@ -80,7 +84,7 @@
       "-isystem$ndk/sources/android/support/include",
       "-isystem$ndk/sources/cxx-stl/llvm-libc++/libcxx/include",
     ]
-    ldflags = [
+    ldflags += [
       "--sysroot=$ndk/platforms/$ndk_platform",
       "--target=$ndk_target",
       "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin",
@@ -104,6 +108,31 @@
   if (is_linux) {
     libs = [ "pthread" ]
   }
+
+  if (sanitize != "") {
+    # You can either pass the sanitizers directly, e.g. "address,undefined",
+    # or pass one of the couple common aliases used by the bots.
+    sanitizers = sanitize
+    if (sanitize == "ASAN") {
+      sanitizers = "address,bool,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr"
+    } else if (sanitize == "TSAN") {
+      sanitizers = "thread"
+    } else if (sanitize == "MSAN") {
+      sanitizers = "memory"
+    }
+
+    cflags += [
+      "-fsanitize=$sanitizers",
+      "-fno-sanitize-recover=$sanitizers",
+      "-fsanitize-blacklist=" + rebase_path("../tools/xsan.blacklist"),
+    ]
+    ldflags += [ "-fsanitize=$sanitizers" ]
+    if (sanitizers == "memory") {
+      cflags += [ "-fsanitize-memory-track-origins" ]
+      cflags_cc += [ "-stdlib=libc++" ]
+      ldflags += [ "-stdlib=libc++" ]
+    }
+  }
 }
 
 config("release") {