From 89285d8f3d3653b37aa9165b05ddbfec50141198 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Wed, 4 Aug 2021 10:13:18 +0200 Subject: Use an LLVM Bazel toolchain in the CI The toolchain is only enabled in the CI by default as users should use the same compiler toolchain for compiling the Jazzer driver as they use to compile their JNI libraries. However, if they are only interested in fuzzing pure Java libraries, they can pass --config=ci on the CLI to use the toolchain, which greatly simplifies the build on macOS. A significant complication arises because the ASan runtime library can't be linked statically on macOS. To make the tests pass, it needs to be exported from the toolchain and the driver has to conditionally depend on it explicitly. A further patch to the toolchain is required to ensure compatibility with Ubuntu 21.04. --- .bazelrc | 6 ++++++ README.md | 3 +++ WORKSPACE.bazel | 25 ++++++++++++++++++++++ driver/BUILD.bazel | 20 ++++++++++++++++- examples/src/main/native/BUILD.bazel | 6 ------ third_party/BUILD.bazel | 17 +++++++++++---- ...bazel-toolchain-export-dynamic-macos-asan.patch | 21 ++++++++++++++++++ .../bazel-toolchain-support-ubuntu-21.patch | 13 +++++++++++ 8 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 third_party/bazel-toolchain-export-dynamic-macos-asan.patch create mode 100644 third_party/bazel-toolchain-support-ubuntu-21.patch diff --git a/.bazelrc b/.bazelrc index cde4cfa2..cd74be05 100644 --- a/.bazelrc +++ b/.bazelrc @@ -11,7 +11,13 @@ build:ci --features=layering_check build --java_language_version=8 build --tool_java_language_version=9 +# Toolchain +build:toolchain --incompatible_enable_cc_toolchain_resolution +build:toolchain --extra_toolchains=@llvm_toolchain//:cc-toolchain-linux,@llvm_toolchain//:cc-toolchain-darwin +build:toolchain --//third_party:toolchain + # RBE +build:ci --config=toolchain build:ci --bes_results_url=https://app.buildbuddy.io/invocation/ build:ci --bes_backend=grpcs://cloud.buildbuddy.io build:ci --remote_cache=grpcs://cloud.buildbuddy.io diff --git a/README.md b/README.md index 79abbb68..7e0cbbd3 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,9 @@ Target //:jazzer_release up-to-date: This will print the path of a `jazzer_release.tar.gz` archive that contains the same binaries that would be part of a release. +The build may fail with the clang shipped with Xcode. If you encounter issues during the build, add `--config=toolchain` +right after `run` or `build` in the `bazelisk` commands above to use a checked-in toolchain that is known to work. + ### Using the provided binaries Binary releases are available under [Releases](https://github.com/CodeIntelligenceTesting/jazzer/releases) and are built diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 358688f7..deaba2e2 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -9,6 +9,31 @@ load("//:init.bzl", "jazzer_init") jazzer_init() +http_archive( + name = "com_grail_bazel_toolchain", + patches = [ + # There is no static runtime library for ASan on macOS, so when using + # the toolchain in the CI, we have to explicitly depend on the dylib and + # add it to the runfiles for clang/ld. + "//third_party:bazel-toolchain-export-dynamic-macos-asan.patch", + "//third_party:bazel-toolchain-support-ubuntu-21.patch", + ], + sha256 = "54b54eedc71b93b278c44b6c056a737dc68545c6da75f63d0810676e1181f559", + strip_prefix = "bazel-toolchain-76ce37e977a304acf8948eadabb82c516320e286", + urls = ["https://github.com/grailbio/bazel-toolchain/archive/76ce37e977a304acf8948eadabb82c516320e286.tar.gz"], +) + +load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies") + +bazel_toolchain_dependencies() + +load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain") + +llvm_toolchain( + name = "llvm_toolchain", + llvm_version = "12.0.0", +) + load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps") rules_jvm_external_deps() diff --git a/driver/BUILD.bazel b/driver/BUILD.bazel index d4d166a2..8a0762ea 100644 --- a/driver/BUILD.bazel +++ b/driver/BUILD.bazel @@ -84,6 +84,16 @@ cc_binary( deps = [":driver_lib"], ) +alias( + name = "using_toolchain_on_osx", + actual = select({ + "//third_party:uses_toolchain": "@platforms//os:osx", + # In order to achieve AND semantics, reference a setting that is known + # not to apply. + "//conditions:default": "//third_party:uses_toolchain", + }), +) + cc_binary( name = "jazzer_driver_asan", data = [ @@ -91,10 +101,16 @@ cc_binary( ], linkopts = [ "-fsanitize=address", + "-static-libsan", "-rdynamic", ], visibility = ["//visibility:public"], - deps = [":driver_lib"], + deps = [":driver_lib"] + select({ + # There is no static ASan runtime on macOS, so link to the dynamic + # runtime library if on macOS and using the toolchain. + ":using_toolchain_on_osx": ["@llvm_toolchain//:macos_asan_dynamic"], + "//conditions:default": [], + }), ) cc_binary( @@ -104,6 +120,8 @@ cc_binary( ], linkopts = [ "-fsanitize=undefined", + # Link UBSan statically, even on macOS. + "-static-libsan", "-rdynamic", ], visibility = ["//visibility:public"], diff --git a/examples/src/main/native/BUILD.bazel b/examples/src/main/native/BUILD.bazel index 32358891..f2587cbe 100644 --- a/examples/src/main/native/BUILD.bazel +++ b/examples/src/main/native/BUILD.bazel @@ -9,9 +9,6 @@ cc_shared_library( copts = [ "-fsanitize=fuzzer-no-link,address", ], - linkopts = [ - "-fsanitize=fuzzer-no-link,address", - ], visibility = ["//examples:__pkg__"], deps = [ "@bazel_tools//tools/jdk:jni", @@ -30,9 +27,6 @@ cc_shared_library( # Workaround for https://github.com/bazelbuild/bazel/issues/11122. "-fno-sanitize=vptr,function", ], - linkopts = [ - "-fsanitize=fuzzer-no-link,undefined", - ], visibility = ["//examples:__pkg__"], deps = [ "@bazel_tools//tools/jdk:jni", diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel index d4c527f8..1ebe86c7 100644 --- a/third_party/BUILD.bazel +++ b/third_party/BUILD.bazel @@ -1,4 +1,13 @@ -exports_files([ - "gflags-use-double-dash-args.patch", - "jacoco-make-probe-inserter-subclassable.patch", -]) +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") + +bool_flag( + name = "toolchain", + build_setting_default = False, +) + +config_setting( + name = "uses_toolchain", + flag_values = { + ":toolchain": "true", + }, +) diff --git a/third_party/bazel-toolchain-export-dynamic-macos-asan.patch b/third_party/bazel-toolchain-export-dynamic-macos-asan.patch new file mode 100644 index 00000000..ccbd79b0 --- /dev/null +++ b/third_party/bazel-toolchain-export-dynamic-macos-asan.patch @@ -0,0 +1,21 @@ +diff --git toolchain/BUILD.tpl toolchain/BUILD.tpl +index bc9280f..f4bfa3d 100644 +--- toolchain/BUILD.tpl ++++ toolchain/BUILD.tpl +@@ -126,6 +126,7 @@ filegroup( + [ + "lib/lib*.a", + "lib/clang/%{llvm_version}/lib/**/*.a", ++ "lib/clang/%{llvm_version}/lib/**/*.dylib", + ], + exclude = [ + "lib/libLLVM*.a", +@@ -216,3 +217,8 @@ filegroup( + ":linker_components", + ], + ) ++ ++cc_import( ++ name = "macos_asan_dynamic", ++ shared_library = "lib/clang/%{llvm_version}/lib/darwin/libclang_rt.asan_osx_dynamic.dylib", ++) diff --git a/third_party/bazel-toolchain-support-ubuntu-21.patch b/third_party/bazel-toolchain-support-ubuntu-21.patch new file mode 100644 index 00000000..b605cfc1 --- /dev/null +++ b/third_party/bazel-toolchain-support-ubuntu-21.patch @@ -0,0 +1,13 @@ +diff --git toolchain/tools/llvm_release_name.py toolchain/tools/llvm_release_name.py +index 8ee544f..86f29f4 100755 +--- toolchain/tools/llvm_release_name.py ++++ toolchain/tools/llvm_release_name.py +@@ -77,7 +77,7 @@ def _linux(llvm_version): + os_name = "linux-sles%s" % version + elif distname == "ubuntu" and version.startswith("14.04"): + os_name = "linux-gnu-ubuntu-14.04" +- elif (distname == "ubuntu" and version.startswith("20.04")) or (distname == "linuxmint" and version.startswith("20")): ++ elif (distname == "ubuntu" and version.startswith("2")) or (distname == "linuxmint" and version.startswith("20")): + if major_llvm_version < 11: + # There is no binary packages specifically for 20.04, but those for 18.04 works on + # 20.04 -- cgit v1.2.3