1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("//build/bazel/product_config:android_product.bzl", "host_platforms") 16load(":cc_library_common.bzl", "path_in_list") 17 18CFI_FEATURE = "android_cfi" 19CFI_ASSEMBLY_FEATURE = "android_cfi_assembly_support" 20DISABLE_CFI_FEATURE = "-" + CFI_FEATURE 21 22# This propagates CFI enablement and disablement down the dependency graph 23def apply_cfi_deps( 24 features, 25 old_cli_features, 26 path, 27 cfi_include_paths, 28 cfi_exclude_paths, 29 enable_cfi, 30 platform): 31 new_cli_features = list(old_cli_features) 32 disabled_by_product_vars = ( 33 not enable_cfi or 34 path_in_list(path, cfi_exclude_paths) 35 ) 36 enabled_by_product_vars = ( 37 path_in_list(path, cfi_include_paths) and _os_is_android(platform[0].name) 38 ) 39 40 # Counterintuitive though it may be, we propagate not only the enablement 41 # of CFI down the dependency graph, but also its disablement 42 if ( 43 CFI_FEATURE in features or 44 enabled_by_product_vars 45 ) and not disabled_by_product_vars: 46 if CFI_FEATURE not in new_cli_features: 47 new_cli_features.append(CFI_FEATURE) 48 if DISABLE_CFI_FEATURE in new_cli_features: 49 new_cli_features.remove(DISABLE_CFI_FEATURE) 50 else: 51 if DISABLE_CFI_FEATURE not in new_cli_features: 52 new_cli_features.append(DISABLE_CFI_FEATURE) 53 if CFI_FEATURE in new_cli_features: 54 new_cli_features.remove(CFI_FEATURE) 55 56 return new_cli_features 57 58# Since CFI is only propagated down static deps, we use this transition to 59# remove it from shared deps that it's added to. It is also used to prevent 60# stub libraries from having two configurations for the same dependency. 61def apply_drop_cfi(old_cli_features): 62 new_cli_features = list(old_cli_features) 63 if CFI_FEATURE in old_cli_features: 64 new_cli_features.remove(CFI_FEATURE) 65 if DISABLE_CFI_FEATURE not in old_cli_features: 66 new_cli_features.append(DISABLE_CFI_FEATURE) 67 return new_cli_features 68 69def _os_is_android(platform): 70 if type(platform) != "string": 71 fail("platform argument should be a string!") 72 for os_suffix in host_platforms: 73 if platform.endswith(os_suffix): 74 return False 75 return True 76