Support "memtag_heap" sanitizer.
Memtag_heap adds an ELF note that enables MTE heap tagging in
bionic/scudo. Ignored on non-executables. With diagnostic
(diag:{memtag_heap:true}) enables the SYNC mode, otherwise - ASYNC mode.
Memtag_heap defaults to set (with diag) on cc_test targets, unset
otherwise. Ignored on non MTE-compatible hardware.
Bug: b/135772972
Test: soong tests
Change-Id: I88fd0f159e609e17bd13487749980a1ba02cb91c
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3502d5f..1ab1b82 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4461,3 +4461,105 @@
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
}
}
+
+func checkHasImplicitDep(t *testing.T, m android.TestingModule, name string) {
+ implicits := m.Rule("ld").Implicits
+ for _, lib := range implicits {
+ if strings.Contains(lib.Rel(), name) {
+ return
+ }
+ }
+
+ t.Errorf("%q is not found in implicit deps of module %q", name, m.Module().(*Module).Name())
+}
+
+func checkDoesNotHaveImplicitDep(t *testing.T, m android.TestingModule, name string) {
+ implicits := m.Rule("ld").Implicits
+ for _, lib := range implicits {
+ if strings.Contains(lib.Rel(), name) {
+ t.Errorf("%q is found in implicit deps of module %q", name, m.Module().(*Module).Name())
+ }
+ }
+}
+
+func TestSanitizeMemtagHeap(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library_static {
+ name: "libstatic",
+ sanitize: { memtag_heap: true },
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ sanitize: { memtag_heap: true },
+ }
+
+ cc_library {
+ name: "libboth",
+ sanitize: { memtag_heap: true },
+ }
+
+ cc_binary {
+ name: "binary",
+ shared_libs: [ "libshared" ],
+ static_libs: [ "libstatic" ],
+ }
+
+ cc_binary {
+ name: "binary_true",
+ sanitize: { memtag_heap: true },
+ }
+
+ cc_binary {
+ name: "binary_true_sync",
+ sanitize: { memtag_heap: true, diag: { memtag_heap: true }, },
+ }
+
+ cc_binary {
+ name: "binary_false",
+ sanitize: { memtag_heap: false },
+ }
+
+ cc_test {
+ name: "test",
+ gtest: false,
+ }
+
+ cc_test {
+ name: "test_true",
+ gtest: false,
+ sanitize: { memtag_heap: true },
+ }
+
+ cc_test {
+ name: "test_false",
+ gtest: false,
+ sanitize: { memtag_heap: false },
+ }
+
+ cc_test {
+ name: "test_true_async",
+ gtest: false,
+ sanitize: { memtag_heap: true, diag: { memtag_heap: false } },
+ }
+
+ `)
+
+ variant := "android_arm64_armv8-a"
+ note_async := "note_memtag_heap_async"
+ note_sync := "note_memtag_heap_sync"
+ note_any := "note_memtag_"
+
+ checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared"), note_any)
+ checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libboth", "android_arm64_armv8-a_shared"), note_any)
+
+ checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary", variant), note_any)
+ checkHasImplicitDep(t, ctx.ModuleForTests("binary_true", variant), note_async)
+ checkHasImplicitDep(t, ctx.ModuleForTests("binary_true_sync", variant), note_sync)
+ checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary_false", variant), note_any)
+
+ checkHasImplicitDep(t, ctx.ModuleForTests("test", variant), note_sync)
+ checkHasImplicitDep(t, ctx.ModuleForTests("test_true", variant), note_async)
+ checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("test_false", variant), note_any)
+ checkHasImplicitDep(t, ctx.ModuleForTests("test_true_async", variant), note_async)
+}