From 3968d8f6780b33ab26c7f9ec06e2fdb6c0f7d26f Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Mon, 14 Dec 2020 11:27:52 -0500 Subject: [PATCH] Refactor CC to prep for Rust sanitizable modules. Adds a PlatformSanitizable interface which both CC and Rust can implement so that the sanitizer mutators in CC can sanitize Rust shared/static libraries appropriately. Bug: 147140513 Test: m nothing Change-Id: Ib31103b6c4902a4d5df2565c0d7c981298d100a3 --- cc/cc.go | 29 +++-- cc/fuzz.go | 2 +- cc/image.go | 40 ++----- cc/linkable.go | 82 +++++++++++++ cc/sanitize.go | 250 +++++++++++++++++++++++++++------------- cc/snapshot_prebuilt.go | 16 +-- cc/vendor_snapshot.go | 2 +- cc/vndk.go | 4 +- rust/binary.go | 4 + rust/compiler.go | 4 + rust/rust.go | 37 ++++++ 11 files changed, 340 insertions(+), 130 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index f45b654da..7a7034f9f 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -57,14 +57,14 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { }) ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.TopDown("asan_deps", sanitizerDepsMutator(asan)) - ctx.BottomUp("asan", sanitizerMutator(asan)).Parallel() + ctx.TopDown("asan_deps", sanitizerDepsMutator(Asan)) + ctx.BottomUp("asan", sanitizerMutator(Asan)).Parallel() ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan)) ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel() - ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(fuzzer)) - ctx.BottomUp("fuzzer", sanitizerMutator(fuzzer)).Parallel() + ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(Fuzzer)) + ctx.BottomUp("fuzzer", sanitizerMutator(Fuzzer)).Parallel() // cfi mutator shouldn't run before sanitizers that return true for // incompatibleWithCfi() @@ -785,6 +785,14 @@ type Module struct { hideApexVariantFromMake bool } +func (c *Module) SetPreventInstall() { + c.Properties.PreventInstall = true +} + +func (c *Module) SetHideFromMake() { + c.Properties.HideFromMake = true +} + func (c *Module) Toc() android.OptionalPath { if c.linker != nil { if library, ok := c.linker.(libraryInterface); ok { @@ -1026,7 +1034,7 @@ func (c *Module) Init() android.Module { // Returns true for dependency roots (binaries) // TODO(ccross): also handle dlopenable libraries -func (c *Module) isDependencyRoot() bool { +func (c *Module) IsDependencyRoot() bool { if root, ok := c.linker.(interface { isDependencyRoot() bool }); ok { @@ -1264,7 +1272,7 @@ func (ctx *moduleContextImpl) staticBinary() bool { } func (ctx *moduleContextImpl) header() bool { - return ctx.mod.header() + return ctx.mod.Header() } func (ctx *moduleContextImpl) binary() bool { @@ -1421,6 +1429,10 @@ func (c *Module) Prebuilt() *android.Prebuilt { return nil } +func (c *Module) IsPrebuilt() bool { + return c.Prebuilt() != nil +} + func (c *Module) Name() string { name := c.ModuleBase.Name() if p, ok := c.linker.(interface { @@ -2847,7 +2859,7 @@ func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, return baseName + ".vendor" } - if c.inVendor() && vendorSuffixModules[baseName] { + if c.InVendor() && vendorSuffixModules[baseName] { return baseName + ".vendor" } else if c.InRecovery() && recoverySuffixModules[baseName] { return baseName + ".recovery" @@ -2959,7 +2971,8 @@ func (c *Module) staticBinary() bool { return false } -func (c *Module) header() bool { +// Header returns true if the module is a header-only variant. (See cc/library.go header()). +func (c *Module) Header() bool { if h, ok := c.linker.(interface { header() bool }); ok { diff --git a/cc/fuzz.go b/cc/fuzz.go index 6b17c48be..a6abb4c1e 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -315,7 +315,7 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module { module, binary := NewBinary(hod) binary.baseInstaller = NewFuzzInstaller() - module.sanitize.SetSanitizer(fuzzer, true) + module.sanitize.SetSanitizer(Fuzzer, true) fuzz := &fuzzBinary{ binaryDecorator: binary, diff --git a/cc/image.go b/cc/image.go index 12bd65b67..13095fca5 100644 --- a/cc/image.go +++ b/cc/image.go @@ -26,36 +26,18 @@ import ( var _ android.ImageInterface = (*Module)(nil) -type imageVariantType string +type ImageVariantType string const ( - coreImageVariant imageVariantType = "core" - vendorImageVariant imageVariantType = "vendor" - productImageVariant imageVariantType = "product" - ramdiskImageVariant imageVariantType = "ramdisk" - vendorRamdiskImageVariant imageVariantType = "vendor_ramdisk" - recoveryImageVariant imageVariantType = "recovery" - hostImageVariant imageVariantType = "host" + coreImageVariant ImageVariantType = "core" + vendorImageVariant ImageVariantType = "vendor" + productImageVariant ImageVariantType = "product" + ramdiskImageVariant ImageVariantType = "ramdisk" + vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk" + recoveryImageVariant ImageVariantType = "recovery" + hostImageVariant ImageVariantType = "host" ) -func (c *Module) getImageVariantType() imageVariantType { - if c.Host() { - return hostImageVariant - } else if c.inVendor() { - return vendorImageVariant - } else if c.InProduct() { - return productImageVariant - } else if c.InRamdisk() { - return ramdiskImageVariant - } else if c.InVendorRamdisk() { - return vendorRamdiskImageVariant - } else if c.InRecovery() { - return recoveryImageVariant - } else { - return coreImageVariant - } -} - const ( // VendorVariationPrefix is the variant prefix used for /vendor code that compiles // against the VNDK. @@ -75,7 +57,7 @@ func (ctx *moduleContext) ProductSpecific() bool { func (ctx *moduleContext) SocSpecific() bool { // Additionally check if this module is inVendor() that means it is a "vendor" variant of a // module. As well as SoC specific modules, vendor variants must be installed to /vendor. - return ctx.ModuleContext.SocSpecific() || ctx.mod.inVendor() + return ctx.ModuleContext.SocSpecific() || ctx.mod.InVendor() } func (ctx *moduleContextImpl) inProduct() bool { @@ -83,7 +65,7 @@ func (ctx *moduleContextImpl) inProduct() bool { } func (ctx *moduleContextImpl) inVendor() bool { - return ctx.mod.inVendor() + return ctx.mod.InVendor() } func (ctx *moduleContextImpl) inRamdisk() bool { @@ -119,7 +101,7 @@ func (c *Module) InProduct() bool { } // Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor -func (c *Module) inVendor() bool { +func (c *Module) InVendor() bool { return c.Properties.ImageVariationPrefix == VendorVariationPrefix } diff --git a/cc/linkable.go b/cc/linkable.go index 489063f1f..ab5a552c1 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -6,6 +6,59 @@ import ( "github.com/google/blueprint" ) +// PlatformSanitizeable is an interface for sanitizing platform modules. +type PlatformSanitizeable interface { + LinkableInterface + + // SanitizePropDefined returns whether the Sanitizer properties struct for this module is defined. + SanitizePropDefined() bool + + // IsDependencyRoot returns whether a module is of a type which cannot be a linkage dependency + // of another module. For example, cc_binary and rust_binary represent dependency roots as other + // modules cannot have linkage dependencies against these types. + IsDependencyRoot() bool + + // IsSanitizerEnabled returns whether a sanitizer is enabled. + IsSanitizerEnabled(t SanitizerType) bool + + // IsSanitizerExplicitlyDisabled returns whether a sanitizer has been explicitly disabled (set to false) rather + // than left undefined. + IsSanitizerExplicitlyDisabled(t SanitizerType) bool + + // SanitizeDep returns the value of the SanitizeDep flag, which is set if a module is a dependency of a + // sanitized module. + SanitizeDep() bool + + // SetSanitizer enables or disables the specified sanitizer type if it's supported, otherwise this should panic. + SetSanitizer(t SanitizerType, b bool) + + // SetSanitizerDep returns true if the module is statically linked. + SetSanitizeDep(b bool) + + // StaticallyLinked returns true if the module is statically linked. + StaticallyLinked() bool + + // SetInSanitizerDir sets the module installation to the sanitizer directory. + SetInSanitizerDir() + + // SanitizeNever returns true if this module should never be sanitized. + SanitizeNever() bool + + // SanitizerSupported returns true if a sanitizer type is supported by this modules compiler. + SanitizerSupported(t SanitizerType) bool + + // SanitizableDepTagChecker returns a SantizableDependencyTagChecker function type. + SanitizableDepTagChecker() SantizableDependencyTagChecker +} + +// SantizableDependencyTagChecker functions check whether or not a dependency +// tag can be sanitized. These functions should return true if the tag can be +// sanitized, otherwise they should return false. These functions should also +// handle all possible dependency tags in the dependency tree. For example, +// Rust modules can depend on both Rust and CC libraries, so the Rust module +// implementation should handle tags from both. +type SantizableDependencyTagChecker func(tag blueprint.DependencyTag) bool + // LinkableInterface is an interface for a type of module that is linkable in a C++ library. type LinkableInterface interface { android.Module @@ -27,6 +80,8 @@ type LinkableInterface interface { SetShared() Static() bool Shared() bool + Header() bool + IsPrebuilt() bool Toc() android.OptionalPath Host() bool @@ -40,6 +95,8 @@ type LinkableInterface interface { InRecovery() bool OnlyInRecovery() bool + InVendor() bool + UseSdk() bool UseVndk() bool MustUseVendorVariant() bool @@ -56,6 +113,11 @@ type LinkableInterface interface { IsSdkVariant() bool SplitPerApiLevel() bool + + // SetPreventInstall sets the PreventInstall property to 'true' for this module. + SetPreventInstall() + // SetHideFromMake sets the HideFromMake property to 'true' for this module. + SetHideFromMake() } var ( @@ -67,6 +129,26 @@ var ( CoverageDepTag = dependencyTag{name: "coverage"} ) +// GetImageVariantType returns the ImageVariantType string value for the given module +// (these are defined in cc/image.go). +func GetImageVariantType(c LinkableInterface) ImageVariantType { + if c.Host() { + return hostImageVariant + } else if c.InVendor() { + return vendorImageVariant + } else if c.InProduct() { + return productImageVariant + } else if c.InRamdisk() { + return ramdiskImageVariant + } else if c.InVendorRamdisk() { + return vendorRamdiskImageVariant + } else if c.InRecovery() { + return recoveryImageVariant + } else { + return coreImageVariant + } +} + // SharedDepTag returns the dependency tag for any C++ shared libraries. func SharedDepTag() blueprint.DependencyTag { return libraryDependencyTag{Kind: sharedLibraryDependency} diff --git a/cc/sanitize.go b/cc/sanitize.go index bb92a882d..599261167 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -71,7 +71,7 @@ var ( "export_memory_stats=0", "max_malloc_fill_size=0"} ) -type sanitizerType int +type SanitizerType int func boolPtr(v bool) *bool { if v { @@ -82,19 +82,19 @@ func boolPtr(v bool) *bool { } const ( - asan sanitizerType = iota + 1 + Asan SanitizerType = iota + 1 hwasan tsan intOverflow cfi scs - fuzzer + Fuzzer ) // Name of the sanitizer variation for this sanitizer type -func (t sanitizerType) variationName() string { +func (t SanitizerType) variationName() string { switch t { - case asan: + case Asan: return "asan" case hwasan: return "hwasan" @@ -106,17 +106,17 @@ func (t sanitizerType) variationName() string { return "cfi" case scs: return "scs" - case fuzzer: + case Fuzzer: return "fuzzer" default: - panic(fmt.Errorf("unknown sanitizerType %d", t)) + panic(fmt.Errorf("unknown SanitizerType %d", t)) } } // This is the sanitizer names in SANITIZE_[TARGET|HOST] -func (t sanitizerType) name() string { +func (t SanitizerType) name() string { switch t { - case asan: + case Asan: return "address" case hwasan: return "hwaddress" @@ -128,15 +128,37 @@ func (t sanitizerType) name() string { return "cfi" case scs: return "shadow-call-stack" - case fuzzer: + case Fuzzer: return "fuzzer" default: - panic(fmt.Errorf("unknown sanitizerType %d", t)) + panic(fmt.Errorf("unknown SanitizerType %d", t)) } } -func (t sanitizerType) incompatibleWithCfi() bool { - return t == asan || t == fuzzer || t == hwasan +func (*Module) SanitizerSupported(t SanitizerType) bool { + switch t { + case Asan: + return true + case hwasan: + return true + case tsan: + return true + case intOverflow: + return true + case cfi: + return true + case scs: + return true + case Fuzzer: + return true + default: + return false + } +} + +// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI. +func (t SanitizerType) incompatibleWithCfi() bool { + return t == Asan || t == Fuzzer || t == hwasan } type SanitizeUserProps struct { @@ -680,9 +702,10 @@ func (sanitize *sanitize) inSanitizerDir() bool { return sanitize.Properties.InSanitizerDir } -func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool { +// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties. +func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { switch t { - case asan: + case Asan: return sanitize.Properties.Sanitize.Address case hwasan: return sanitize.Properties.Sanitize.Hwaddress @@ -694,32 +717,34 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool { return sanitize.Properties.Sanitize.Cfi case scs: return sanitize.Properties.Sanitize.Scs - case fuzzer: + case Fuzzer: return sanitize.Properties.Sanitize.Fuzzer default: - panic(fmt.Errorf("unknown sanitizerType %d", t)) + panic(fmt.Errorf("unknown SanitizerType %d", t)) } } +// isUnsanitizedVariant returns true if no sanitizers are enabled. func (sanitize *sanitize) isUnsanitizedVariant() bool { - return !sanitize.isSanitizerEnabled(asan) && + return !sanitize.isSanitizerEnabled(Asan) && !sanitize.isSanitizerEnabled(hwasan) && !sanitize.isSanitizerEnabled(tsan) && !sanitize.isSanitizerEnabled(cfi) && !sanitize.isSanitizerEnabled(scs) && - !sanitize.isSanitizerEnabled(fuzzer) + !sanitize.isSanitizerEnabled(Fuzzer) } +// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled). func (sanitize *sanitize) isVariantOnProductionDevice() bool { - return !sanitize.isSanitizerEnabled(asan) && + return !sanitize.isSanitizerEnabled(Asan) && !sanitize.isSanitizerEnabled(hwasan) && !sanitize.isSanitizerEnabled(tsan) && - !sanitize.isSanitizerEnabled(fuzzer) + !sanitize.isSanitizerEnabled(Fuzzer) } -func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { +func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { switch t { - case asan: + case Asan: sanitize.Properties.Sanitize.Address = boolPtr(b) case hwasan: sanitize.Properties.Sanitize.Hwaddress = boolPtr(b) @@ -731,10 +756,10 @@ func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { sanitize.Properties.Sanitize.Cfi = boolPtr(b) case scs: sanitize.Properties.Sanitize.Scs = boolPtr(b) - case fuzzer: + case Fuzzer: sanitize.Properties.Sanitize.Fuzzer = boolPtr(b) default: - panic(fmt.Errorf("unknown sanitizerType %d", t)) + panic(fmt.Errorf("unknown SanitizerType %d", t)) } if b { sanitize.Properties.SanitizerEnabled = true @@ -743,7 +768,7 @@ func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { // Check if the sanitizer is explicitly disabled (as opposed to nil by // virtue of not being set). -func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool { +func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool { if sanitize == nil { return false } @@ -757,7 +782,7 @@ func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool { // indirectly (via a mutator) sets the bool ptr to true, and you can't // distinguish between the cases. It isn't needed though - both cases can be // treated identically. -func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { +func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool { if sanitize == nil { return false } @@ -766,7 +791,8 @@ func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { return sanitizerVal != nil && *sanitizerVal == true } -func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { +// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable. +func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool { switch t := tag.(type) { case dependencyTag: return t == reuseObjTag || t == objDepTag @@ -777,6 +803,10 @@ func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { } } +func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker { + return IsSanitizableDependencyTag +} + // Determines if the current module is a static library going to be captured // as vendor snapshot. Such modules must create both cfi and non-cfi variants, // except for ones which explicitly disable cfi. @@ -785,51 +815,58 @@ func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool { return false } - c := mctx.Module().(*Module) + c := mctx.Module().(PlatformSanitizeable) - if !c.inVendor() { + if !c.InVendor() { return false } - if !c.static() { + if !c.StaticallyLinked() { return false } - if c.Prebuilt() != nil { + if c.IsPrebuilt() { return false } - return c.sanitize != nil && - !Bool(c.sanitize.Properties.Sanitize.Never) && - !c.sanitize.isSanitizerExplicitlyDisabled(cfi) + if !c.SanitizerSupported(cfi) { + return false + } + + return c.SanitizePropDefined() && + !c.SanitizeNever() && + !c.IsSanitizerExplicitlyDisabled(cfi) } // Propagate sanitizer requirements down from binaries -func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) { +func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) { return func(mctx android.TopDownMutatorContext) { - if c, ok := mctx.Module().(*Module); ok { - enabled := c.sanitize.isSanitizerEnabled(t) + if c, ok := mctx.Module().(PlatformSanitizeable); ok { + enabled := c.IsSanitizerEnabled(t) if t == cfi && needsCfiForVendorSnapshot(mctx) { // We shouldn't change the result of isSanitizerEnabled(cfi) to correctly // determine defaultVariation in sanitizerMutator below. // Instead, just mark SanitizeDep to forcefully create cfi variant. enabled = true - c.sanitize.Properties.SanitizeDep = true + c.SetSanitizeDep(true) } if enabled { + isSanitizableDependencyTag := c.SanitizableDepTagChecker() mctx.WalkDeps(func(child, parent android.Module) bool { if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) { return false } - if d, ok := child.(*Module); ok && d.sanitize != nil && - !Bool(d.sanitize.Properties.Sanitize.Never) && - !d.sanitize.isSanitizerExplicitlyDisabled(t) { + if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() && + !d.SanitizeNever() && + !d.IsSanitizerExplicitlyDisabled(t) { if t == cfi || t == hwasan || t == scs { - if d.static() { - d.sanitize.Properties.SanitizeDep = true + if d.StaticallyLinked() && d.SanitizerSupported(t) { + // Rust does not support some of these sanitizers, so we need to check if it's + // supported before setting this true. + d.SetSanitizeDep(true) } } else { - d.sanitize.Properties.SanitizeDep = true + d.SetSanitizeDep(true) } } return true @@ -847,9 +884,19 @@ func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) { } } +func (c *Module) SanitizeNever() bool { + return Bool(c.sanitize.Properties.Sanitize.Never) +} + +func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool { + return c.sanitize.isSanitizerExplicitlyDisabled(t) +} + // Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies. func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) { + // Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers. if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { + isSanitizableDependencyTag := c.SanitizableDepTagChecker() mctx.WalkDeps(func(child, parent android.Module) bool { if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) { return false @@ -1057,7 +1104,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { variations = append(variations, c.ImageVariation()) } mctx.AddFarVariationDependencies(variations, depTag, deps...) - } else if !c.static() && !c.header() { + } else if !c.static() && !c.Header() { // If we're using snapshots and in vendor, redirect to snapshot whenever possible if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() { snapshots := vendorSnapshotSharedLibs(mctx.Config()) @@ -1098,16 +1145,52 @@ type Sanitizeable interface { AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) } +func (c *Module) SanitizePropDefined() bool { + return c.sanitize != nil +} + +func (c *Module) IsSanitizerEnabled(t SanitizerType) bool { + return c.sanitize.isSanitizerEnabled(t) +} + +func (c *Module) SanitizeDep() bool { + return c.sanitize.Properties.SanitizeDep +} + +func (c *Module) StaticallyLinked() bool { + return c.static() +} + +func (c *Module) SetInSanitizerDir() { + if c.sanitize != nil { + c.sanitize.Properties.InSanitizerDir = true + } +} + +func (c *Module) SetSanitizer(t SanitizerType, b bool) { + if c.sanitize != nil { + c.sanitize.SetSanitizer(t, b) + } +} + +func (c *Module) SetSanitizeDep(b bool) { + if c.sanitize != nil { + c.sanitize.Properties.SanitizeDep = b + } +} + +var _ PlatformSanitizeable = (*Module)(nil) + // Create sanitized variants for modules that need them -func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { +func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { return func(mctx android.BottomUpMutatorContext) { - if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { - if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) { + if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() { + if c.IsDependencyRoot() && c.IsSanitizerEnabled(t) { modules := mctx.CreateVariations(t.variationName()) - modules[0].(*Module).sanitize.SetSanitizer(t, true) - } else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep { - isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t) - if c.static() || c.header() || t == asan || t == fuzzer { + modules[0].(PlatformSanitizeable).SetSanitizer(t, true) + } else if c.IsSanitizerEnabled(t) || c.SanitizeDep() { + isSanitizerEnabled := c.IsSanitizerEnabled(t) + if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer { // Static and header libs are split into non-sanitized and sanitized variants. // Shared libs are not split. However, for asan and fuzzer, we split even for shared // libs because a library sanitized for asan/fuzzer can't be linked from a library @@ -1121,17 +1204,20 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { // module. By setting it to the name of the sanitized variation, the dangling dependency // is redirected to the sanitized variant of the dependent module. defaultVariation := t.variationName() + // Not all PlatformSanitizeable modules support the CFI sanitizer + cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi) mctx.SetDefaultDependencyVariation(&defaultVariation) - modules := mctx.CreateVariations("", t.variationName()) - modules[0].(*Module).sanitize.SetSanitizer(t, false) - modules[1].(*Module).sanitize.SetSanitizer(t, true) - modules[0].(*Module).sanitize.Properties.SanitizeDep = false - modules[1].(*Module).sanitize.Properties.SanitizeDep = false - if mctx.Device() && t.incompatibleWithCfi() { + modules := mctx.CreateVariations("", t.variationName()) + modules[0].(PlatformSanitizeable).SetSanitizer(t, false) + modules[1].(PlatformSanitizeable).SetSanitizer(t, true) + modules[0].(PlatformSanitizeable).SetSanitizeDep(false) + modules[1].(PlatformSanitizeable).SetSanitizeDep(false) + + if mctx.Device() && t.incompatibleWithCfi() && cfiSupported { // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that // are incompatible with cfi - modules[1].(*Module).sanitize.SetSanitizer(cfi, false) + modules[1].(PlatformSanitizeable).SetSanitizer(cfi, false) } // For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants @@ -1139,46 +1225,48 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { // For other types of sanitizers, suppress the variation that is disabled. if t != cfi && t != scs && t != hwasan { if isSanitizerEnabled { - modules[0].(*Module).Properties.PreventInstall = true - modules[0].(*Module).Properties.HideFromMake = true + modules[0].(PlatformSanitizeable).SetPreventInstall() + modules[0].(PlatformSanitizeable).SetHideFromMake() } else { - modules[1].(*Module).Properties.PreventInstall = true - modules[1].(*Module).Properties.HideFromMake = true + modules[1].(PlatformSanitizeable).SetPreventInstall() + modules[1].(PlatformSanitizeable).SetHideFromMake() } } // Export the static lib name to make - if c.static() && c.ExportedToMake() { + if c.StaticallyLinked() && c.ExportedToMake() { if t == cfi { - cfiStaticLibs(mctx.Config()).add(c, c.Name()) + cfiStaticLibs(mctx.Config()).add(c, c.Module().Name()) } else if t == hwasan { - hwasanStaticLibs(mctx.Config()).add(c, c.Name()) + hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name()) } } } else { // Shared libs are not split. Only the sanitized variant is created. modules := mctx.CreateVariations(t.variationName()) - modules[0].(*Module).sanitize.SetSanitizer(t, true) - modules[0].(*Module).sanitize.Properties.SanitizeDep = false + modules[0].(PlatformSanitizeable).SetSanitizer(t, true) + modules[0].(PlatformSanitizeable).SetSanitizeDep(false) // locate the asan libraries under /data/asan - if mctx.Device() && t == asan && isSanitizerEnabled { - modules[0].(*Module).sanitize.Properties.InSanitizerDir = true + if mctx.Device() && t == Asan && isSanitizerEnabled { + modules[0].(PlatformSanitizeable).SetInSanitizerDir() } if mctx.Device() && t.incompatibleWithCfi() { // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that // are incompatible with cfi - modules[0].(*Module).sanitize.SetSanitizer(cfi, false) + modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false) } } } - c.sanitize.Properties.SanitizeDep = false + c.SetSanitizeDep(false) } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) { // APEX modules fall here sanitizeable.AddSanitizerDependencies(mctx, t.name()) mctx.CreateVariations(t.variationName()) } else if c, ok := mctx.Module().(*Module); ok { + //TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable + // Check if it's a snapshot module supporting sanitizer if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) { // Set default variation as above. @@ -1203,23 +1291,23 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { type sanitizerStaticLibsMap struct { // libsMap contains one list of modules per each image and each arch. // e.g. libs[vendor]["arm"] contains arm modules installed to vendor - libsMap map[imageVariantType]map[string][]string + libsMap map[ImageVariantType]map[string][]string libsMapLock sync.Mutex - sanitizerType sanitizerType + sanitizerType SanitizerType } -func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap { +func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap { return &sanitizerStaticLibsMap{ sanitizerType: t, - libsMap: make(map[imageVariantType]map[string][]string), + libsMap: make(map[ImageVariantType]map[string][]string), } } // Add the current module to sanitizer static libs maps // Each module should pass its exported name as names of Make and Soong can differ. -func (s *sanitizerStaticLibsMap) add(c *Module, name string) { - image := c.getImageVariantType() - arch := c.Arch().ArchType.String() +func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) { + image := GetImageVariantType(c) + arch := c.Module().Target().Arch.ArchType.String() s.libsMapLock.Lock() defer s.libsMapLock.Unlock() @@ -1238,7 +1326,7 @@ func (s *sanitizerStaticLibsMap) add(c *Module, name string) { // See build/make/core/binary.mk for more details. func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) { for _, image := range android.SortedStringKeys(s.libsMap) { - archMap := s.libsMap[imageVariantType(image)] + archMap := s.libsMap[ImageVariantType(image)] for _, arch := range android.SortedStringKeys(archMap) { libs := archMap[arch] sort.Strings(libs) diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index e3f3a4d67..89798468c 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -104,7 +104,7 @@ func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) } func (vendorSnapshotImage) inImage(m *Module) func() bool { - return m.inVendor + return m.InVendor } func (vendorSnapshotImage) available(m *Module) *bool { @@ -507,8 +507,8 @@ type snapshotLibraryProperties struct { } type snapshotSanitizer interface { - isSanitizerEnabled(t sanitizerType) bool - setSanitizerVariation(t sanitizerType, enabled bool) + isSanitizerEnabled(t SanitizerType) bool + setSanitizerVariation(t SanitizerType, enabled bool) } type snapshotLibraryDecorator struct { @@ -546,7 +546,7 @@ func (p *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { m := ctx.Module().(*Module) - if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { + if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = vendorSuffix } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = recoverySuffix @@ -613,7 +613,7 @@ func (p *snapshotLibraryDecorator) nativeCoverage() bool { return false } -func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { +func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool { switch t { case cfi: return p.sanitizerProperties.Cfi.Src != nil @@ -622,7 +622,7 @@ func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { } } -func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { +func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) { if !enabled { return } @@ -769,7 +769,7 @@ func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps Path binName := in.Base() m := ctx.Module().(*Module) - if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { + if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = vendorSuffix } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = recoverySuffix @@ -868,7 +868,7 @@ func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDep m := ctx.Module().(*Module) - if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { + if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = vendorSuffix } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] { p.androidMkSuffix = recoverySuffix diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 622ebec45..0a89e471c 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -247,7 +247,7 @@ func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInf if m.sanitize != nil { // scs and hwasan export both sanitized and unsanitized variants for static and header // Always use unsanitized variants of them. - for _, t := range []sanitizerType{scs, hwasan} { + for _, t := range []SanitizerType{scs, hwasan} { if !l.shared() && m.sanitize.isSanitizerEnabled(t) { return false } diff --git a/cc/vndk.go b/cc/vndk.go index c1264f743..daae1f7bd 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -394,7 +394,7 @@ func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() && mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant() - return lib.shared() && m.inVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant + return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant } return false } @@ -586,7 +586,7 @@ func isVndkSnapshotAware(config android.DeviceConfig, m *Module, // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants. // !installable: Snapshot only cares about "installable" modules. // isSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. - if !m.inVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() { + if !m.InVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() { return nil, "", false } l, ok := m.linker.(snapshotLibraryInterface) diff --git a/rust/binary.go b/rust/binary.go index c2d97f3ab..ca07d07c1 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -164,3 +164,7 @@ func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage { } return binary.baseCompiler.stdLinkage(ctx) } + +func (binary *binaryDecorator) isDependencyRoot() bool { + return true +} diff --git a/rust/compiler.go b/rust/compiler.go index ee88a273f..bcea6cccc 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -236,6 +236,10 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) } +func (compiler *baseCompiler) isDependencyRoot() bool { + return false +} + func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...) diff --git a/rust/rust.go b/rust/rust.go index 105384676..1fa97af96 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -106,6 +106,42 @@ type Module struct { hideApexVariantFromMake bool } +func (mod *Module) Header() bool { + //TODO: If Rust libraries provide header variants, this needs to be updated. + return false +} + +func (mod *Module) SetPreventInstall() { + mod.Properties.PreventInstall = true +} + +// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor +func (mod *Module) InVendor() bool { + return mod.Properties.ImageVariationPrefix == cc.VendorVariationPrefix +} + +func (mod *Module) SetHideFromMake() { + mod.Properties.HideFromMake = true +} + +func (mod *Module) SanitizePropDefined() bool { + return false +} + +func (mod *Module) IsDependencyRoot() bool { + if mod.compiler != nil { + return mod.compiler.isDependencyRoot() + } + panic("IsDependencyRoot called on a non-compiler Rust module") +} + +func (mod *Module) IsPrebuilt() bool { + if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok { + return true + } + return false +} + func (mod *Module) OutputFiles(tag string) (android.Paths, error) { switch tag { case "": @@ -281,6 +317,7 @@ type compiler interface { SetDisabled() stdLinkage(ctx *depsContext) RustLinkage + isDependencyRoot() bool } type exportedFlagsProducer interface {