Add sanitizer tests for musl

Add tests that verify sanitizer behaviors for musl.

Test: sanitize_test.go
Change-Id: I1f0a51cc103ac14d1738cb223e216ee0e32d8550
This commit is contained in:
Colin Cross 2023-02-15 12:20:19 -08:00
parent 9e87f0a6ea
commit 5dc62c9456
5 changed files with 164 additions and 23 deletions

View file

@ -401,7 +401,7 @@ func TestArchMutator(t *testing.T) {
{
name: "same arch host and host cross",
preparer: FixtureModifyConfig(func(config Config) {
modifyTestConfigForMusl(config)
ModifyTestConfigForMusl(config)
modifyTestConfigForMuslArm64HostCross(config)
}),
fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
@ -705,7 +705,7 @@ func TestArchProperties(t *testing.T) {
{
name: "linux_musl",
goOS: "linux",
preparer: FixtureModifyConfig(modifyTestConfigForMusl),
preparer: FixtureModifyConfig(ModifyTestConfigForMusl),
results: []result{
{
module: "foo",

View file

@ -16,6 +16,7 @@ package android
import (
"fmt"
"runtime"
"strings"
"testing"
)
@ -379,6 +380,12 @@ func FixtureModifyProductVariables(mutator func(variables FixtureProductVariable
})
}
var PrepareForSkipTestOnMac = newSimpleFixturePreparer(func(fixture *fixture) {
if runtime.GOOS != "linux" {
fixture.t.Skip("Test is only supported on linux.")
}
})
// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
// state before running the test.
//

View file

@ -109,7 +109,8 @@ func modifyTestConfigToSupportArchMutator(testConfig Config) {
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
}
func modifyTestConfigForMusl(config Config) {
// ModifyTestConfigForMusl takes a Config returned by TestConfig and changes the host targets from glibc to musl.
func ModifyTestConfigForMusl(config Config) {
delete(config.Targets, config.BuildOS)
config.productVariables.HostMusl = boolPtr(true)
determineBuildOS(config.config)

View file

@ -28,12 +28,22 @@ import (
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
cc_library_shared {
name: "libclang_rt.asan",
host_supported: true,
}
cc_library_static {
name: "libclang_rt.asan.static",
host_supported: true,
}
cc_library_static {
name: "libclang_rt.asan_cxx.static",
host_supported: true,
}
`))
var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
cc_library_shared {
name: "libclang_rt.tsan",
host_supported: true,
}
`))
@ -54,6 +64,19 @@ func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.T
}
}
// expectNoSharedLinkDep verifies that the from module links against the to module as a
// shared library.
func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
from.Module(), to.Module(), w, g)
}
}
// expectStaticLinkDep verifies that the from module links against the to module as a
// static library.
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
@ -68,6 +91,20 @@ func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.T
}
// expectNoStaticLinkDep verifies that the from module links against the to module as a
// static library.
func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
from.Module(), to.Module(), w, g)
}
}
// expectInstallDep verifies that the install rule of the from module depends on the
// install rule of the to module.
func expectInstallDep(t *testing.T, from, to android.TestingModule) {
@ -85,6 +122,13 @@ func expectInstallDep(t *testing.T, from, to android.TestingModule) {
}
}
type expectedRuntimeLinkage int
const (
RUNTIME_LINKAGE_NONE = expectedRuntimeLinkage(0)
RUNTIME_LINKAGE_SHARED = iota
)
func TestAsan(t *testing.T) {
t.Parallel()
bp := `
@ -162,12 +206,14 @@ func TestAsan(t *testing.T) {
`
result := android.GroupFixturePreparers(
preparer := android.GroupFixturePreparers(
prepareForCcTest,
prepareForAsanTest,
).RunTestWithBp(t, bp)
)
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) {
check := func(t *testing.T, variant string, runtimeLinkage expectedRuntimeLinkage, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
asanVariant := variant + "_asan"
sharedVariant := variant + "_shared"
@ -198,6 +244,8 @@ func TestAsan(t *testing.T) {
libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
expectSharedLinkDep(t, ctx, binWithAsan, libShared)
expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
expectSharedLinkDep(t, ctx, libShared, libTransitive)
@ -227,10 +275,28 @@ func TestAsan(t *testing.T) {
expectInstallDep(t, binNoAsan, libTransitive)
expectInstallDep(t, libShared, libTransitive)
expectInstallDep(t, libAsan, libTransitive)
if runtimeLinkage == RUNTIME_LINKAGE_SHARED {
expectSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
expectSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
} else {
expectNoSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
}
}
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", RUNTIME_LINKAGE_SHARED, preparer) })
t.Run("host musl", func(t *testing.T) {
check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_SHARED,
android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
})
}
func TestTsan(t *testing.T) {
@ -278,12 +344,14 @@ func TestTsan(t *testing.T) {
}
`
result := android.GroupFixturePreparers(
preparer := android.GroupFixturePreparers(
prepareForCcTest,
prepareForTsanTest,
).RunTestWithBp(t, bp)
)
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) {
check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
tsanVariant := variant + "_tsan"
sharedVariant := variant + "_shared"
@ -311,8 +379,11 @@ func TestTsan(t *testing.T) {
expectSharedLinkDep(t, ctx, libTsan, libTransitive)
}
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
t.Run("host musl", func(t *testing.T) {
check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
})
}
func TestMiscUndefined(t *testing.T) {
@ -369,11 +440,13 @@ func TestMiscUndefined(t *testing.T) {
}
`
result := android.GroupFixturePreparers(
preparer := android.GroupFixturePreparers(
prepareForCcTest,
).RunTestWithBp(t, bp)
)
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) {
check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
staticVariant := variant + "_static"
@ -415,8 +488,11 @@ func TestMiscUndefined(t *testing.T) {
expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
}
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
t.Run("host musl", func(t *testing.T) {
check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
})
}
func TestFuzz(t *testing.T) {
@ -647,11 +723,13 @@ func TestUbsan(t *testing.T) {
}
`
result := android.GroupFixturePreparers(
preparer := android.GroupFixturePreparers(
prepareForCcTest,
).RunTestWithBp(t, bp)
)
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) {
check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
staticVariant := variant + "_static"
sharedVariant := variant + "_shared"
@ -705,8 +783,11 @@ func TestUbsan(t *testing.T) {
"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
}
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
t.Run("host musl", func(t *testing.T) {
check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
})
}
type MemtagNoteType int

View file

@ -70,6 +70,7 @@ func commonDefaultModules() string {
return `
cc_defaults {
name: "toolchain_libs_defaults",
host_supported: true,
vendor_available: true,
product_available: true,
recovery_available: true,
@ -134,6 +135,12 @@ func commonDefaultModules() string {
srcs: [""],
}
cc_prebuilt_library_static {
name: "libclang_rt.ubsan_standalone.static",
defaults: ["toolchain_libs_defaults"],
srcs: [""],
}
cc_prebuilt_library_static {
name: "libclang_rt.ubsan_minimal",
defaults: ["toolchain_libs_defaults"],
@ -151,6 +158,12 @@ func commonDefaultModules() string {
linux_glibc_x86: {
srcs: ["libclang_rt.ubsan_minimal.x86.a"],
},
linux_musl_x86_64: {
srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
},
linux_musl_x86: {
srcs: ["libclang_rt.ubsan_minimal.x86.a"],
},
},
}
@ -619,6 +632,45 @@ var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
}),
)
// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc. It also disables the test
// on mac, which doesn't support musl libc, and adds musl modules.
var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
android.FixtureModifyConfig(android.ModifyTestConfigForMusl),
android.PrepareForSkipTestOnMac,
android.FixtureAddTextFile("external/musl/Android.bp", `
cc_defaults {
name: "libc_musl_crt_defaults",
host_supported: true,
device_supported: false,
}
cc_object {
name: "libc_musl_crtbegin_so",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtend_so",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtbegin_dynamic",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtbegin_static",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtend",
defaults: ["libc_musl_crt_defaults"],
}
`),
)
// TestConfig is the legacy way of creating a test Config for testing cc modules.
//
// See testCc for an explanation as to how to stop using this deprecated method.