xref: /aosp_15_r20/build/bazel/toolchains/clang/host/linux-x86/cc_toolchain_features_cfi_test.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
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