aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrevor Radcliffe <tradical@google.com>2023-03-22 20:17:39 +0000
committerTrevor Radcliffe <tradical@google.com>2023-03-27 18:06:15 +0000
commit17387cc815397ad58828cb166384dfc282325a7d (patch)
tree9a4babf04f58687a17f6b3c5e97fdc7322407aaf
parentb3c6fd30ce498a7d8696f526e59e10cb27939f86 (diff)
downloadlinux-x86-17387cc815397ad58828cb166384dfc282325a7d.tar.gz
Introduce toolchain features for CFI
Bug: 251217226 Test: Unit Tests Change-Id: Iae460ebf9860bb1250be5a9d4cca0acfe7ceb219
-rw-r--r--BUILD.bazel8
-rw-r--r--cc_toolchain_config.bzl9
-rw-r--r--cc_toolchain_constants.bzl4
-rw-r--r--cc_toolchain_features.bzl73
-rw-r--r--cc_toolchain_features_cfi_test.bzl254
5 files changed, 348 insertions, 0 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
index 00c980bc9..45ad95681 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -37,6 +37,10 @@ load(
_musl_crt = "musl_crt",
)
load(
+ ":cc_toolchain_features_cfi_test.bzl",
+ "cc_toolchain_features_cfi_test_suite",
+)
+load(
":cc_toolchain_features_pack_relocation_test.bzl",
"cc_toolchain_features_pack_relocation_test_suite",
)
@@ -403,6 +407,10 @@ filegroup(
visibility = ["//build/bazel/tests:__subpackages__"],
)
+cc_toolchain_features_cfi_test_suite(
+ name = "cc_toolchain_features_cfi_tests",
+)
+
cc_toolchain_features_pack_relocation_test_suite(
name = "cc_toolchain_features_pack_relocation_tests",
)
diff --git a/cc_toolchain_config.bzl b/cc_toolchain_config.bzl
index fc8762f67..ff201ca3b 100644
--- a/cc_toolchain_config.bzl
+++ b/cc_toolchain_config.bzl
@@ -17,6 +17,7 @@ load(
_enabled_features = "enabled_features",
_flags = "flags",
_generated_config_constants = "generated_config_constants",
+ _generated_sanitizer_constants = "generated_sanitizer_constants",
)
load(
":cc_toolchain_features.bzl",
@@ -336,6 +337,14 @@ def android_cc_toolchain(
if gcc_toolchain:
gcc_toolchain_path = "//%s:tools" % gcc_toolchain
extra_linker_paths.append(gcc_toolchain_path)
+ extra_linker_paths.append("//%s:%s" % (
+ _generated_sanitizer_constants.CfiExportsMapPath,
+ _generated_sanitizer_constants.CfiExportsMapFilename,
+ ))
+ extra_linker_paths.append("//%s:%s" % (
+ _generated_sanitizer_constants.CfiBlocklistPath,
+ _generated_sanitizer_constants.CfiBlocklistFilename,
+ ))
common_toolchain_config = dict(
[
diff --git a/cc_toolchain_constants.bzl b/cc_toolchain_constants.bzl
index 52f19e2e6..9dde758c6 100644
--- a/cc_toolchain_constants.bzl
+++ b/cc_toolchain_constants.bzl
@@ -59,6 +59,10 @@ actions = struct(
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
],
+ c_and_cpp_compile = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ],
c_compile = ACTION_NAMES.c_compile,
cpp_compile = ACTION_NAMES.cpp_compile,
# Assembler actions for .s and .S files.
diff --git a/cc_toolchain_features.bzl b/cc_toolchain_features.bzl
index e04030478..7b26f5710 100644
--- a/cc_toolchain_features.bzl
+++ b/cc_toolchain_features.bzl
@@ -1586,6 +1586,78 @@ def _get_thinlto_features():
]
return features
+def _make_flag_set(actions, flags):
+ return flag_set(
+ actions = actions,
+ flag_groups = [
+ flag_group(
+ flags = flags,
+ ),
+ ],
+ )
+
+def _get_cfi_features(target_arch, target_os):
+ if target_os in [_oses.Windows, _oses.Darwin]:
+ return []
+ features = [
+ feature(
+ name = "android_cfi",
+ enabled = False,
+ flag_sets = [
+ _make_flag_set(
+ _actions.c_and_cpp_compile,
+ _generated_sanitizer_constants.CfiCFlags,
+ ),
+ _make_flag_set(
+ _actions.link,
+ _generated_sanitizer_constants.CfiLdFlags,
+ ),
+ _make_flag_set(
+ _actions.assemble,
+ _generated_sanitizer_constants.CfiAsFlags,
+ ),
+ ],
+ implies = ["android_thin_lto"] + (
+ ["arm_isa_thumb"] if target_arch == _arches.Arm else []
+ ),
+ ),
+ ]
+
+ features += [
+ feature(
+ name = "android_cfi_assembly_support",
+ enabled = False,
+ requires = [feature_set(features = ["android_cfi"])],
+ flag_sets = [
+ _make_flag_set(
+ _actions.c_and_cpp_compile,
+ [_generated_sanitizer_constants.CfiAssemblySupportFlag],
+ ),
+ ],
+ ),
+ ]
+
+ features += [
+ feature(
+ name = "android_cfi_exports_map",
+ enabled = False,
+ requires = [feature_set(features = ["android_cfi"])],
+ flag_sets = [
+ _make_flag_set(
+ _actions.link,
+ [
+ _generated_config_constants.VersionScriptFlagPrefix +
+ _generated_sanitizer_constants.CfiExportsMapPath +
+ "/" +
+ _generated_sanitizer_constants.CfiExportsMapFilename,
+ ],
+ ),
+ ],
+ ),
+ ]
+
+ return features
+
def _ubsan_flag_feature(name, actions, flags):
return feature(
name = name,
@@ -1937,6 +2009,7 @@ def get_features(
# Optimization
_get_thinlto_features(),
# Sanitizers
+ _get_cfi_features(target_arch, target_os),
_get_ubsan_features(target_os, libclang_rt_ubsan_minimal),
# This must always come last.
_link_crtend(crt_files),
diff --git a/cc_toolchain_features_cfi_test.bzl b/cc_toolchain_features_cfi_test.bzl
new file mode 100644
index 000000000..2a3e0a39b
--- /dev/null
+++ b/cc_toolchain_features_cfi_test.bzl
@@ -0,0 +1,254 @@
+"""Copyright (C) 2022 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+ ":cc_toolchain_constants.bzl",
+ "generated_config_constants",
+ "generated_sanitizer_constants",
+)
+load(
+ "//build/bazel/rules/test_common:flags.bzl",
+ "action_flags_absent_for_mnemonic_test",
+ "action_flags_present_for_mnemonic_nonexclusive_test",
+ "action_flags_present_only_for_mnemonic_test",
+)
+
+compile_action_mnemonic = "CppCompile"
+link_action_mnemonic = "CppLink"
+
+def test_cfi_c_and_cpp_has_correct_flags():
+ name = "cfi_c_and_cpp_has_correct_flags"
+ native.cc_binary(
+ name = name,
+ srcs = ["foo.c", "bar.cpp"],
+ features = ["android_cfi"],
+ tags = ["manual"],
+ )
+
+ compile_test_name = name + "_compile_test"
+ action_flags_present_for_mnemonic_nonexclusive_test(
+ name = compile_test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_flags = generated_sanitizer_constants.CfiCFlags,
+ )
+
+ link_test_name = name + "_link_test"
+ action_flags_present_for_mnemonic_nonexclusive_test(
+ name = link_test_name,
+ target_under_test = name,
+ mnemonics = [link_action_mnemonic],
+ expected_flags = generated_sanitizer_constants.CfiLdFlags,
+ )
+
+ compile_no_assemble_flags_test_name = "_compile_no_assemble_flags_test"
+ action_flags_absent_for_mnemonic_test(
+ name = compile_no_assemble_flags_test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_absent_flags = generated_sanitizer_constants.CfiAsFlags,
+ )
+
+ return [
+ compile_test_name,
+ link_test_name,
+ compile_no_assemble_flags_test_name,
+ ]
+
+def test_cfi_s_has_correct_flags():
+ name = "cfi_s_has_correct_flags"
+ native.cc_binary(
+ name = name,
+ srcs = ["baz.s", "blah.S"],
+ features = ["android_cfi"],
+ tags = ["manual"],
+ )
+
+ assemble_test_name = name + "_assemble_test"
+ action_flags_present_only_for_mnemonic_test(
+ name = assemble_test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_flags = generated_sanitizer_constants.CfiAsFlags,
+ )
+
+ compile_flags_absent_test_name = name + "_compile_flags_absent_test"
+ action_flags_absent_for_mnemonic_test(
+ name = compile_flags_absent_test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_absent_flags = generated_sanitizer_constants.CfiCFlags,
+ )
+
+ return [
+ assemble_test_name,
+ compile_flags_absent_test_name,
+ ]
+
+def test_cfi_assembly_support_has_correct_flags():
+ name = "cfi_assembly_support_has_correct_flags"
+ native.cc_binary(
+ name = name,
+ srcs = ["foo.c", "bar.cpp"],
+ features = [
+ "android_cfi",
+ "android_cfi_assembly_support",
+ ],
+ tags = ["manual"],
+ )
+
+ test_name = name + "_test"
+ action_flags_present_only_for_mnemonic_test(
+ name = test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_flags = [generated_sanitizer_constants.CfiAssemblySupportFlag],
+ )
+
+ return test_name
+
+def test_cfi_assembly_support_does_not_add_flags_for_s():
+ name = "cfi_assembly_support_does_not_add_flags_for_s"
+ native.cc_binary(
+ name = name,
+ srcs = ["baz.s", "blah.S"],
+ features = [
+ "android_cfi",
+ "android_cfi_assembly_support",
+ ],
+ tags = ["manual"],
+ )
+
+ test_name = name + "_test"
+ action_flags_absent_for_mnemonic_test(
+ name = test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_absent_flags = [
+ generated_sanitizer_constants.CfiAssemblySupportFlag,
+ ],
+ )
+
+ return test_name
+
+def test_cfi_exports_map_has_correct_flags():
+ name = "cfi_exports_map_has_correct_flags"
+ native.cc_binary(
+ name = name,
+ srcs = ["foo.c", "bar.cpp"],
+ features = [
+ "android_cfi",
+ "android_cfi_exports_map",
+ ],
+ tags = ["manual"],
+ )
+
+ test_name = name + "_test"
+ action_flags_present_only_for_mnemonic_test(
+ name = test_name,
+ target_under_test = name,
+ mnemonics = [link_action_mnemonic],
+ expected_flags = [
+ generated_config_constants.VersionScriptFlagPrefix +
+ generated_sanitizer_constants.CfiExportsMapPath +
+ "/" +
+ generated_sanitizer_constants.CfiExportsMapFilename,
+ ],
+ )
+
+ return test_name
+
+def test_cfi_implies_lto():
+ name = "cfi_implies_lto"
+ native.cc_binary(
+ name = name,
+ srcs = ["foo.c", "bar.cpp"],
+ features = ["android_cfi"],
+ tags = ["manual"],
+ )
+
+ test_name = name + "_test"
+ action_flags_present_for_mnemonic_nonexclusive_test(
+ name = test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_flags = ["-flto=thin"],
+ )
+
+ return test_name
+
+def test_cfi_and_arm_uses_thumb():
+ name = "cfi_and_arm_uses_thumb"
+ native.cc_binary(
+ name = name,
+ srcs = ["foo.c", "bar.cpp"],
+ features = ["android_cfi"],
+ tags = ["manual"],
+ )
+
+ test_name = name + "_test"
+ action_flags_present_for_mnemonic_nonexclusive_test(
+ name = test_name,
+ target_under_test = name,
+ mnemonics = [compile_action_mnemonic],
+ expected_flags = generated_config_constants.ArmThumbCflags,
+ target_compatible_with = [
+ "//build/bazel/platforms/arch:arm",
+ ],
+ )
+
+ return test_name
+
+# TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
+#def test_cfi_absent_on_darwin_and_windows():
+# name = "cfi_absent_on_darwin_and_windows"
+# native.cc_binary(
+# name = name,
+# srcs = ["foo.c", "bar.cpp"],
+# features = ["android_cfi"]
+# tags = ["manual"],
+# )
+#
+# test_name = name + "_test"
+# action_flags_absent_for_mnemonic_test(
+# name = test_name,
+# target_under_test = name,
+# mnemonics = [compile_action_mnemonic],
+# expected_absent_flags = generated_sanitizer_constants.CfiCFlags,
+# target_compatible_with = [
+# "//build/bazel/platforms/os:darwin",
+# "//build/bazel/platforms/os:windows",
+# ]
+# )
+#
+# return test_name
+
+def cc_toolchain_features_cfi_test_suite(name):
+ individual_tests = [
+ test_cfi_assembly_support_has_correct_flags(),
+ test_cfi_assembly_support_does_not_add_flags_for_s(),
+ test_cfi_exports_map_has_correct_flags(),
+ test_cfi_implies_lto(),
+ test_cfi_and_arm_uses_thumb(),
+ # TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
+ # test_cfi_absent_on_darwin_and_windows(),
+ ]
+ native.test_suite(
+ name = name,
+ tests = individual_tests +
+ test_cfi_c_and_cpp_has_correct_flags() +
+ test_cfi_s_has_correct_flags(),
+ )