1"""Copyright (C) 2022 The Android Open Source Project 2 3Licensed under the Apache License, Version 2.0 (the "License"); 4you may not use this file except in compliance with the License. 5You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9Unless required by applicable law or agreed to in writing, software 10distributed under the License is distributed on an "AS IS" BASIS, 11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12See the License for the specific language governing permissions and 13limitations under the License. 14""" 15 16load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 17load( 18 ":cc_toolchain_constants.bzl", 19 "generated_config_constants", 20 "generated_sanitizer_constants", 21) 22load( 23 "//build/bazel/rules/test_common:flags.bzl", 24 "action_flags_absent_for_mnemonic_aosp_arm64_host_test", 25 "action_flags_absent_for_mnemonic_aosp_arm64_test", 26 "action_flags_absent_for_mnemonic_test", 27 "action_flags_present_for_mnemonic_nonexclusive_test", 28 "action_flags_present_only_for_mnemonic_aosp_arm64_host_test", 29 "action_flags_present_only_for_mnemonic_aosp_arm64_test", 30 "action_flags_present_only_for_mnemonic_test", 31) 32 33compile_action_mnemonic = "CppCompile" 34link_action_mnemonic = "CppLink" 35 36# Include these different file types to make sure that all actions types are 37# triggered 38test_srcs = [ 39 "foo.cpp", 40 "bar.c", 41 "baz.s", 42 "blah.S", 43] 44 45def test_cfi_c_and_cpp_has_correct_flags(): 46 name = "cfi_c_and_cpp_has_correct_flags" 47 native.cc_binary( 48 name = name, 49 srcs = ["foo.c", "bar.cpp"], 50 features = ["android_cfi"], 51 tags = ["manual"], 52 ) 53 54 compile_test_name = name + "_compile_test" 55 action_flags_present_for_mnemonic_nonexclusive_test( 56 name = compile_test_name, 57 target_under_test = name, 58 mnemonics = [compile_action_mnemonic], 59 expected_flags = generated_sanitizer_constants.CfiCFlags + 60 [generated_sanitizer_constants.CfiCrossDsoFlag], 61 ) 62 63 link_test_name = name + "_link_test" 64 action_flags_present_for_mnemonic_nonexclusive_test( 65 name = link_test_name, 66 target_under_test = name, 67 mnemonics = [link_action_mnemonic], 68 expected_flags = generated_sanitizer_constants.CfiLdFlags + 69 [generated_sanitizer_constants.CfiCrossDsoFlag], 70 ) 71 72 return [ 73 compile_test_name, 74 link_test_name, 75 ] 76 77def test_cfi_s_has_correct_flags(): 78 name = "cfi_s_has_correct_flags" 79 native.cc_binary( 80 name = name, 81 srcs = ["baz.s", "blah.S"], 82 features = ["android_cfi"], 83 tags = ["manual"], 84 ) 85 86 assemble_test_name = name + "_assemble_test" 87 action_flags_present_only_for_mnemonic_test( 88 name = assemble_test_name, 89 target_under_test = name, 90 mnemonics = [compile_action_mnemonic], 91 expected_flags = generated_sanitizer_constants.CfiAsFlags, 92 ) 93 94 compile_flags_absent_test_name = name + "_compile_flags_absent_test" 95 action_flags_absent_for_mnemonic_test( 96 name = compile_flags_absent_test_name, 97 target_under_test = name, 98 mnemonics = [compile_action_mnemonic], 99 expected_absent_flags = generated_sanitizer_constants.CfiCFlags + 100 [generated_sanitizer_constants.CfiCrossDsoFlag], 101 ) 102 103 return [ 104 assemble_test_name, 105 compile_flags_absent_test_name, 106 ] 107 108def test_cross_dso_not_added_when_cfi_disabled(): 109 name = "cross_dso_not_added_when_cfi_disabled" 110 native.cc_binary( 111 name = name, 112 srcs = ["foo.c", "bar.cpp"], 113 features = ["android_cfi_cross_dso"], 114 tags = ["manual"], 115 ) 116 117 test_name = name + "_test" 118 action_flags_absent_for_mnemonic_test( 119 name = test_name, 120 target_under_test = name, 121 mnemonics = [compile_action_mnemonic, link_action_mnemonic], 122 expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag], 123 ) 124 125 return test_name 126 127def test_cross_dso_not_added_when_static_binary(): 128 name = "cross_dso_not_added_when_static_binary" 129 native.cc_binary( 130 name = name, 131 srcs = ["foo.c", "bar.cpp"], 132 features = [ 133 "android_cfi", 134 "static_executable", 135 "-dynamic_executable", 136 "android_cfi_cross_dso", 137 ], 138 tags = ["manual"], 139 ) 140 141 android_test_name = name + "_android_test" 142 action_flags_absent_for_mnemonic_test( 143 name = android_test_name, 144 target_under_test = name, 145 mnemonics = [compile_action_mnemonic, link_action_mnemonic], 146 expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag], 147 target_compatible_with = ["//build/bazel_common_rules/platforms/os:android"], 148 ) 149 150 linux_test_name = name + "_linux_test" 151 action_flags_absent_for_mnemonic_test( 152 name = linux_test_name, 153 target_under_test = name, 154 mnemonics = [compile_action_mnemonic, link_action_mnemonic], 155 expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag], 156 target_compatible_with = ["//build/bazel_common_rules/platforms/os:linux_glibc"], 157 ) 158 159 return [ 160 android_test_name, 161 linux_test_name, 162 ] 163 164def test_cfi_assembly_support_has_correct_flags(): 165 name = "cfi_assembly_support_has_correct_flags" 166 native.cc_binary( 167 name = name, 168 srcs = ["foo.c", "bar.cpp"], 169 features = [ 170 "android_cfi", 171 "android_cfi_assembly_support", 172 ], 173 tags = ["manual"], 174 ) 175 176 test_name = name + "_test" 177 action_flags_present_only_for_mnemonic_test( 178 name = test_name, 179 target_under_test = name, 180 mnemonics = [compile_action_mnemonic], 181 expected_flags = [generated_sanitizer_constants.CfiAssemblySupportFlag], 182 ) 183 184 return test_name 185 186def test_cfi_assembly_support_does_not_add_flags_for_s(): 187 name = "cfi_assembly_support_does_not_add_flags_for_s" 188 native.cc_binary( 189 name = name, 190 srcs = ["baz.s", "blah.S"], 191 features = [ 192 "android_cfi", 193 "android_cfi_assembly_support", 194 ], 195 tags = ["manual"], 196 ) 197 198 test_name = name + "_test" 199 action_flags_absent_for_mnemonic_test( 200 name = test_name, 201 target_under_test = name, 202 mnemonics = [compile_action_mnemonic], 203 expected_absent_flags = [ 204 generated_sanitizer_constants.CfiAssemblySupportFlag, 205 ], 206 ) 207 208 return test_name 209 210def test_cfi_exports_map_has_correct_flags(): 211 name = "cfi_exports_map_has_correct_flags" 212 native.cc_binary( 213 name = name, 214 srcs = ["foo.c", "bar.cpp"], 215 features = [ 216 "android_cfi", 217 "android_cfi_exports_map", 218 ], 219 tags = ["manual"], 220 ) 221 222 test_name = name + "_test" 223 action_flags_present_only_for_mnemonic_test( 224 name = test_name, 225 target_under_test = name, 226 mnemonics = [link_action_mnemonic], 227 expected_flags = [ 228 generated_config_constants.VersionScriptFlagPrefix + 229 generated_sanitizer_constants.CfiExportsMapPath + 230 "/" + 231 generated_sanitizer_constants.CfiExportsMapFilename, 232 ], 233 ) 234 235 return test_name 236 237def test_cfi_cross_dso_has_correct_flags(): 238 name = "cfi_cross_dso_has_correct_flags" 239 native.cc_binary( 240 name = name, 241 srcs = ["foo.c", "bar.cpp"], 242 features = [ 243 "android_cfi", 244 "android_cfi_cross_dso", 245 ], 246 tags = ["manual"], 247 ) 248 249 test_name = name + "_test" 250 action_flags_present_only_for_mnemonic_test( 251 name = test_name, 252 target_under_test = name, 253 mnemonics = [compile_action_mnemonic, link_action_mnemonic], 254 expected_flags = [generated_sanitizer_constants.CfiCrossDsoFlag], 255 ) 256 257 return test_name 258 259def test_cfi_cross_dso_does_not_add_flags_for_s(): 260 name = "cfi_cross_dso_does_not_add_flags_for_s" 261 native.cc_binary( 262 name = name, 263 srcs = ["baz.s", "blah.S"], 264 features = [ 265 "android_cfi", 266 "android_cfi_cross_dso", 267 ], 268 tags = ["manual"], 269 ) 270 271 test_name = name + "_test" 272 action_flags_absent_for_mnemonic_test( 273 name = test_name, 274 target_under_test = name, 275 mnemonics = [compile_action_mnemonic], 276 expected_absent_flags = [generated_sanitizer_constants.CfiCrossDsoFlag], 277 ) 278 279 return test_name 280 281# TODO(b/283951987): Swtich to thin LTO when possible 282def test_cfi_implies_lto(): 283 name = "cfi_implies_lto" 284 native.cc_binary( 285 name = name, 286 srcs = ["foo.c", "bar.cpp"], 287 features = ["android_cfi"], 288 tags = ["manual"], 289 ) 290 291 test_name = name + "_test" 292 action_flags_present_for_mnemonic_nonexclusive_test( 293 name = test_name, 294 target_under_test = name, 295 mnemonics = [compile_action_mnemonic], 296 expected_flags = ["-flto"], 297 ) 298 299 return test_name 300 301def test_cfi_implies_vis_default_if_not_hidden(): 302 name = "cfi_implies_vis_default_if_not_hidden" 303 native.cc_binary( 304 name = name, 305 srcs = ["foo.c", "bar.cpp"], 306 features = ["android_cfi"], 307 tags = ["manual"], 308 ) 309 310 test_name = name + "_test" 311 action_flags_present_only_for_mnemonic_test( 312 name = test_name, 313 target_under_test = name, 314 mnemonics = [compile_action_mnemonic], 315 expected_flags = ["-fvisibility=default"], 316 ) 317 318 return test_name 319 320def test_cfi_does_not_add_vis_default_if_hidden(): 321 name = "cfi_does_not_add_vis_default_if_hidden" 322 native.cc_binary( 323 name = name, 324 srcs = ["foo.c", "bar.cpp"], 325 features = ["android_cfi", "visibility_hidden"], 326 tags = ["manual"], 327 ) 328 329 test_name = name + "_test" 330 action_flags_absent_for_mnemonic_test( 331 name = test_name, 332 target_under_test = name, 333 mnemonics = [compile_action_mnemonic], 334 expected_absent_flags = ["-fvisibility=default"], 335 ) 336 337 return test_name 338 339def test_cfi_and_arm_uses_thumb(): 340 name = "cfi_and_arm_uses_thumb" 341 native.cc_binary( 342 name = name, 343 srcs = ["foo.c", "bar.cpp"], 344 features = ["android_cfi"], 345 tags = ["manual"], 346 ) 347 348 test_name = name + "_test" 349 action_flags_present_for_mnemonic_nonexclusive_test( 350 name = test_name, 351 target_under_test = name, 352 mnemonics = [compile_action_mnemonic], 353 expected_flags = generated_config_constants.ArmThumbCflags, 354 target_compatible_with = [ 355 "//build/bazel_common_rules/platforms/arch:arm", 356 ], 357 ) 358 359 return test_name 360 361# TODO(b/274924237): Uncomment after Darwin and Windows have toolchains 362#def test_cfi_absent_on_unsupported_oses(): 363# name = "cfi_absent_on_unsupported_oses" 364# native.cc_binary( 365# name = name, 366# srcs = ["foo.c", "bar.cpp"], 367# features = ["android_cfi"], 368# tags = ["manual"], 369# ) 370# 371# test_name = name + "_test" 372# action_flags_absent_for_mnemonic_test( 373# name = test_name, 374# target_under_test = name, 375# mnemonics = [compile_action_mnemonic], 376# expected_absent_flags = generated_sanitizer_constants.CfiCFlags, 377# target_compatible_with = [ 378# "//build/bazel_common_rules/platforms/os:linux_musl", 379# "//build/bazel_common_rules/platforms/os:darwin", 380# "//build/bazel_common_rules/platforms/os:windows", 381# ] 382# ) 383# 384# return test_name 385 386def _test_host_only_and_device_only_features(): 387 name = "cfi_host_only_and_device_only_features" 388 test_names = [] 389 390 native.cc_binary( 391 name = name, 392 srcs = ["foo.c", "bar.cpp"], 393 features = ["android_cfi"], 394 tags = ["manual"], 395 ) 396 397 host_with_host_flags_test_name = name + "_host_flags_present_when_host_test" 398 test_names += [host_with_host_flags_test_name] 399 action_flags_present_only_for_mnemonic_aosp_arm64_host_test( 400 name = host_with_host_flags_test_name, 401 target_under_test = name, 402 mnemonics = [compile_action_mnemonic], 403 expected_flags = generated_sanitizer_constants.HostOnlySanitizeFlags, 404 ) 405 406 device_with_host_flags_test_name = name + "_host_flags_absent_when_device_test" 407 test_names += [device_with_host_flags_test_name] 408 action_flags_absent_for_mnemonic_aosp_arm64_test( 409 name = device_with_host_flags_test_name, 410 target_under_test = name, 411 mnemonics = [compile_action_mnemonic], 412 expected_absent_flags = generated_sanitizer_constants.HostOnlySanitizeFlags, 413 ) 414 415 device_with_device_flags_test_name = name + "_device_flags_present_when_device_test" 416 test_names += [device_with_device_flags_test_name] 417 action_flags_present_only_for_mnemonic_aosp_arm64_test( 418 name = device_with_device_flags_test_name, 419 target_under_test = name, 420 mnemonics = [compile_action_mnemonic], 421 expected_flags = generated_sanitizer_constants.DeviceOnlySanitizeFlags, 422 ) 423 424 host_with_device_flags_test_name = name + "_device_flags_absent_when_host_test" 425 test_names += [host_with_device_flags_test_name] 426 action_flags_absent_for_mnemonic_aosp_arm64_host_test( 427 name = host_with_device_flags_test_name, 428 target_under_test = name, 429 mnemonics = [compile_action_mnemonic], 430 expected_absent_flags = generated_sanitizer_constants.DeviceOnlySanitizeFlags, 431 ) 432 433 return test_names 434 435def _test_device_only_and_host_only_features_absent_when_cfi_disabled(): 436 pass 437 438def _test_cfi_no_link_runtime(): 439 name = "cfi_no_link_runtime" 440 441 native.cc_binary( 442 name = name, 443 srcs = test_srcs, 444 features = ["android_cfi"], 445 tags = ["manual"], 446 ) 447 448 android_test_name = name + "_when_android_test" 449 test_names = [android_test_name] 450 action_flags_present_only_for_mnemonic_aosp_arm64_test( 451 name = android_test_name, 452 target_under_test = name, 453 mnemonics = [link_action_mnemonic], 454 expected_flags = [ 455 generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag, 456 ], 457 ) 458 459 host_test_name = name + "_not_supplied_when_host_test" 460 test_names += [host_test_name] 461 action_flags_absent_for_mnemonic_aosp_arm64_host_test( 462 name = host_test_name, 463 target_under_test = name, 464 mnemonics = [link_action_mnemonic], 465 expected_absent_flags = [ 466 generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag, 467 ], 468 ) 469 470 # TODO: b/263787980 - Implement test for bionic 471 # TODO: b/263787526 - Implement test for musl 472 473 return test_names 474 475def cc_toolchain_features_cfi_test_suite(name): 476 individual_tests = [ 477 test_cross_dso_not_added_when_cfi_disabled(), 478 test_cfi_assembly_support_has_correct_flags(), 479 test_cfi_assembly_support_does_not_add_flags_for_s(), 480 test_cfi_exports_map_has_correct_flags(), 481 test_cfi_cross_dso_has_correct_flags(), 482 test_cfi_cross_dso_does_not_add_flags_for_s(), 483 test_cfi_implies_lto(), 484 test_cfi_implies_vis_default_if_not_hidden(), 485 test_cfi_does_not_add_vis_default_if_hidden(), 486 test_cfi_and_arm_uses_thumb(), 487 # TODO(b/274924237): Uncomment after Darwin and Windows have toolchains 488 # test_cfi_absent_on_unsupported_oses(), 489 ] 490 native.test_suite( 491 name = name, 492 tests = individual_tests + 493 test_cfi_c_and_cpp_has_correct_flags() + 494 test_cfi_s_has_correct_flags() + 495 test_cross_dso_not_added_when_static_binary() + 496 _test_host_only_and_device_only_features() + 497 _test_cfi_no_link_runtime(), 498 ) 499