diff options
author | Trevor Radcliffe <tradical@google.com> | 2023-03-22 20:17:39 +0000 |
---|---|---|
committer | Trevor Radcliffe <tradical@google.com> | 2023-03-27 18:06:15 +0000 |
commit | 17387cc815397ad58828cb166384dfc282325a7d (patch) | |
tree | 9a4babf04f58687a17f6b3c5e97fdc7322407aaf | |
parent | b3c6fd30ce498a7d8696f526e59e10cb27939f86 (diff) | |
download | linux-x86-17387cc815397ad58828cb166384dfc282325a7d.tar.gz |
Introduce toolchain features for CFI
Bug: 251217226
Test: Unit Tests
Change-Id: Iae460ebf9860bb1250be5a9d4cca0acfe7ceb219
-rw-r--r-- | BUILD.bazel | 8 | ||||
-rw-r--r-- | cc_toolchain_config.bzl | 9 | ||||
-rw-r--r-- | cc_toolchain_constants.bzl | 4 | ||||
-rw-r--r-- | cc_toolchain_features.bzl | 73 | ||||
-rw-r--r-- | cc_toolchain_features_cfi_test.bzl | 254 |
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(), + ) |