diff --git a/cc/Android.bp b/cc/Android.bp index 9ece05f6c..831911e45 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -19,6 +19,7 @@ bootstrap_go_package { "check.go", "coverage.go", "gen.go", + "image.go", "linkable.go", "lto.go", "makevars.go", diff --git a/cc/cc.go b/cc/cc.go index d099b043e..4b362184a 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1027,48 +1027,6 @@ func (c *Module) getVndkExtendsModuleName() string { return "" } -// Returns true only when this module is configured to have core, product and vendor -// variants. -func (c *Module) HasVendorVariant() bool { - return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) -} - -const ( - // VendorVariationPrefix is the variant prefix used for /vendor code that compiles - // against the VNDK. - VendorVariationPrefix = "vendor." - - // ProductVariationPrefix is the variant prefix used for /product code that compiles - // against the VNDK. - ProductVariationPrefix = "product." -) - -// Returns true if the module is "product" variant. Usually these modules are installed in /product -func (c *Module) inProduct() bool { - return c.Properties.ImageVariationPrefix == ProductVariationPrefix -} - -// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor -func (c *Module) inVendor() bool { - return c.Properties.ImageVariationPrefix == VendorVariationPrefix -} - -func (c *Module) InRamdisk() bool { - return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk() -} - -func (c *Module) InRecovery() bool { - return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery() -} - -func (c *Module) OnlyInRamdisk() bool { - return c.ModuleBase.InstallInRamdisk() -} - -func (c *Module) OnlyInRecovery() bool { - return c.ModuleBase.InstallInRecovery() -} - func (c *Module) IsStubs() bool { if library, ok := c.linker.(*libraryDecorator); ok { return library.buildStubs() @@ -1176,16 +1134,6 @@ type moduleContext struct { moduleContextImpl } -func (ctx *moduleContext) ProductSpecific() bool { - return ctx.ModuleContext.ProductSpecific() || - (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk()) -} - -func (ctx *moduleContext) SocSpecific() bool { - return ctx.ModuleContext.SocSpecific() || - (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk()) -} - type moduleContextImpl struct { mod *Module ctx BaseModuleContext @@ -1281,22 +1229,6 @@ func (ctx *moduleContextImpl) mustUseVendorVariant() bool { return ctx.mod.MustUseVendorVariant() } -func (ctx *moduleContextImpl) inProduct() bool { - return ctx.mod.inProduct() -} - -func (ctx *moduleContextImpl) inVendor() bool { - return ctx.mod.inVendor() -} - -func (ctx *moduleContextImpl) inRamdisk() bool { - return ctx.mod.InRamdisk() -} - -func (ctx *moduleContextImpl) inRecovery() bool { - return ctx.mod.InRecovery() -} - // Check whether ABI dumps should be created for this module. func (ctx *moduleContextImpl) shouldCreateSourceAbiDump() bool { if ctx.ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { @@ -3143,236 +3075,6 @@ func squashRecoverySrcs(m *Module) { } } -var _ android.ImageInterface = (*Module)(nil) - -func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { - // Validation check - vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() - productSpecific := mctx.ProductSpecific() - - if m.VendorProperties.Vendor_available != nil && vendorSpecific { - mctx.PropertyErrorf("vendor_available", - "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`") - } - - if vndkdep := m.vndkdep; vndkdep != nil { - if vndkdep.isVndk() { - if vendorSpecific || productSpecific { - if !vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `extends: \"...\"` to vndk extension") - } else if m.VendorProperties.Vendor_available != nil { - mctx.PropertyErrorf("vendor_available", - "must not set at the same time as `vndk: {extends: \"...\"}`") - } - } else { - if vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `vendor: true` or `product_specific: true` to set `extends: %q`", - m.getVndkExtendsModuleName()) - } - if m.VendorProperties.Vendor_available == nil { - mctx.PropertyErrorf("vndk", - "vendor_available must be set to either true or false when `vndk: {enabled: true}`") - } - } - } else { - if vndkdep.isVndkSp() { - mctx.PropertyErrorf("vndk", - "must set `enabled: true` to set `support_system_process: true`") - } - if vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `enabled: true` to set `extends: %q`", - m.getVndkExtendsModuleName()) - } - } - } - - var coreVariantNeeded bool = false - var ramdiskVariantNeeded bool = false - var recoveryVariantNeeded bool = false - - var vendorVariants []string - var productVariants []string - - platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion() - boardVndkVersion := mctx.DeviceConfig().VndkVersion() - productVndkVersion := mctx.DeviceConfig().ProductVndkVersion() - if boardVndkVersion == "current" { - boardVndkVersion = platformVndkVersion - } - if productVndkVersion == "current" { - productVndkVersion = platformVndkVersion - } - - if boardVndkVersion == "" { - // If the device isn't compiling against the VNDK, we always - // use the core mode. - coreVariantNeeded = true - } else if _, ok := m.linker.(*llndkStubDecorator); ok { - // LL-NDK stubs only exist in the vendor and product variants, - // since the real libraries will be used in the core variant. - vendorVariants = append(vendorVariants, - platformVndkVersion, - boardVndkVersion, - ) - productVariants = append(productVariants, - platformVndkVersion, - productVndkVersion, - ) - } else if _, ok := m.linker.(*llndkHeadersDecorator); ok { - // ... and LL-NDK headers as well - vendorVariants = append(vendorVariants, - platformVndkVersion, - boardVndkVersion, - ) - productVariants = append(productVariants, - platformVndkVersion, - productVndkVersion, - ) - } else if m.isSnapshotPrebuilt() { - // Make vendor variants only for the versions in BOARD_VNDK_VERSION and - // PRODUCT_EXTRA_VNDK_VERSIONS. - if snapshot, ok := m.linker.(interface { - version() string - }); ok { - vendorVariants = append(vendorVariants, snapshot.version()) - } else { - mctx.ModuleErrorf("version is unknown for snapshot prebuilt") - } - } else if m.HasVendorVariant() && !m.isVndkExt() { - // This will be available in /system, /vendor and /product - // or a /system directory that is available to vendor and product. - coreVariantNeeded = true - - // We assume that modules under proprietary paths are compatible for - // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or - // PLATFORM_VNDK_VERSION. - if isVendorProprietaryPath(mctx.ModuleDir()) { - vendorVariants = append(vendorVariants, boardVndkVersion) - } else { - vendorVariants = append(vendorVariants, platformVndkVersion) - } - - // vendor_available modules are also available to /product. - productVariants = append(productVariants, platformVndkVersion) - // VNDK is always PLATFORM_VNDK_VERSION - if !m.IsVndk() { - productVariants = append(productVariants, productVndkVersion) - } - } else if vendorSpecific && String(m.Properties.Sdk_version) == "" { - // This will be available in /vendor (or /odm) only - - // kernel_headers is a special module type whose exported headers - // are coming from DeviceKernelHeaders() which is always vendor - // dependent. They'll always have both vendor variants. - // For other modules, we assume that modules under proprietary - // paths are compatible for BOARD_VNDK_VERSION. The other modules - // are regarded as AOSP, which is PLATFORM_VNDK_VERSION. - if _, ok := m.linker.(*kernelHeadersDecorator); ok { - vendorVariants = append(vendorVariants, - platformVndkVersion, - boardVndkVersion, - ) - } else if isVendorProprietaryPath(mctx.ModuleDir()) { - vendorVariants = append(vendorVariants, boardVndkVersion) - } else { - vendorVariants = append(vendorVariants, platformVndkVersion) - } - } else { - // This is either in /system (or similar: /data), or is a - // modules built with the NDK. Modules built with the NDK - // will be restricted using the existing link type checks. - coreVariantNeeded = true - } - - if boardVndkVersion != "" && productVndkVersion != "" { - if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" { - // The module has "product_specific: true" that does not create core variant. - coreVariantNeeded = false - productVariants = append(productVariants, productVndkVersion) - } - } else { - // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no - // restriction to use system libs. - // No product variants defined in this case. - productVariants = []string{} - } - - if Bool(m.Properties.Ramdisk_available) { - ramdiskVariantNeeded = true - } - - if m.ModuleBase.InstallInRamdisk() { - ramdiskVariantNeeded = true - coreVariantNeeded = false - } - - if Bool(m.Properties.Recovery_available) { - recoveryVariantNeeded = true - } - - if m.ModuleBase.InstallInRecovery() { - recoveryVariantNeeded = true - coreVariantNeeded = false - } - - for _, variant := range android.FirstUniqueStrings(vendorVariants) { - m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant) - } - - for _, variant := range android.FirstUniqueStrings(productVariants) { - m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant) - } - - m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded - m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded - m.Properties.CoreVariantNeeded = coreVariantNeeded -} - -func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool { - return c.Properties.CoreVariantNeeded -} - -func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return c.Properties.RamdiskVariantNeeded -} - -func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { - return c.Properties.RecoveryVariantNeeded -} - -func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string { - return c.Properties.ExtraVariants -} - -func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) { - m := module.(*Module) - if variant == android.RamdiskVariation { - m.MakeAsPlatform() - } else if variant == android.RecoveryVariation { - m.MakeAsPlatform() - squashRecoverySrcs(m) - } else if strings.HasPrefix(variant, VendorVariationPrefix) { - m.Properties.ImageVariationPrefix = VendorVariationPrefix - m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix) - squashVendorSrcs(m) - - // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION. - // Hide other vendor variants to avoid collision. - vndkVersion := ctx.DeviceConfig().VndkVersion() - if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion { - m.Properties.HideFromMake = true - m.SkipInstall() - } - } else if strings.HasPrefix(variant, ProductVariationPrefix) { - m.Properties.ImageVariationPrefix = ProductVariationPrefix - m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix) - squashVendorSrcs(m) - } -} - func (c *Module) IsSdkVariant() bool { return c.Properties.IsSdkVariant } diff --git a/cc/image.go b/cc/image.go new file mode 100644 index 000000000..4daed7c00 --- /dev/null +++ b/cc/image.go @@ -0,0 +1,348 @@ +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package cc + +// This file contains image variant related things, including image mutator functions, utility +// functions to determine where a module is installed, etc. + +import ( + "strings" + + "android/soong/android" +) + +var _ android.ImageInterface = (*Module)(nil) + +type imageVariantType string + +const ( + coreImageVariant imageVariantType = "core" + vendorImageVariant imageVariantType = "vendor" + productImageVariant imageVariantType = "product" + ramdiskImageVariant imageVariantType = "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.InRecovery() { + return recoveryImageVariant + } else { + return coreImageVariant + } +} + +const ( + // VendorVariationPrefix is the variant prefix used for /vendor code that compiles + // against the VNDK. + VendorVariationPrefix = "vendor." + + // ProductVariationPrefix is the variant prefix used for /product code that compiles + // against the VNDK. + ProductVariationPrefix = "product." +) + +func (ctx *moduleContext) ProductSpecific() bool { + return ctx.ModuleContext.ProductSpecific() || + (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk()) +} + +func (ctx *moduleContext) SocSpecific() bool { + return ctx.ModuleContext.SocSpecific() || + (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk()) +} + +func (ctx *moduleContextImpl) inProduct() bool { + return ctx.mod.inProduct() +} + +func (ctx *moduleContextImpl) inVendor() bool { + return ctx.mod.inVendor() +} + +func (ctx *moduleContextImpl) inRamdisk() bool { + return ctx.mod.InRamdisk() +} + +func (ctx *moduleContextImpl) inRecovery() bool { + return ctx.mod.InRecovery() +} + +// Returns true only when this module is configured to have core, product and vendor +// variants. +func (c *Module) HasVendorVariant() bool { + return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) +} + +// Returns true if the module is "product" variant. Usually these modules are installed in /product +func (c *Module) inProduct() bool { + return c.Properties.ImageVariationPrefix == ProductVariationPrefix +} + +// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor +func (c *Module) inVendor() bool { + return c.Properties.ImageVariationPrefix == VendorVariationPrefix +} + +func (c *Module) InRamdisk() bool { + return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk() +} + +func (c *Module) InRecovery() bool { + return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery() +} + +func (c *Module) OnlyInRamdisk() bool { + return c.ModuleBase.InstallInRamdisk() +} + +func (c *Module) OnlyInRecovery() bool { + return c.ModuleBase.InstallInRecovery() +} + +func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { + // Validation check + vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() + productSpecific := mctx.ProductSpecific() + + if m.VendorProperties.Vendor_available != nil && vendorSpecific { + mctx.PropertyErrorf("vendor_available", + "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`") + } + + if vndkdep := m.vndkdep; vndkdep != nil { + if vndkdep.isVndk() { + if vendorSpecific || productSpecific { + if !vndkdep.isVndkExt() { + mctx.PropertyErrorf("vndk", + "must set `extends: \"...\"` to vndk extension") + } else if m.VendorProperties.Vendor_available != nil { + mctx.PropertyErrorf("vendor_available", + "must not set at the same time as `vndk: {extends: \"...\"}`") + } + } else { + if vndkdep.isVndkExt() { + mctx.PropertyErrorf("vndk", + "must set `vendor: true` or `product_specific: true` to set `extends: %q`", + m.getVndkExtendsModuleName()) + } + if m.VendorProperties.Vendor_available == nil { + mctx.PropertyErrorf("vndk", + "vendor_available must be set to either true or false when `vndk: {enabled: true}`") + } + } + } else { + if vndkdep.isVndkSp() { + mctx.PropertyErrorf("vndk", + "must set `enabled: true` to set `support_system_process: true`") + } + if vndkdep.isVndkExt() { + mctx.PropertyErrorf("vndk", + "must set `enabled: true` to set `extends: %q`", + m.getVndkExtendsModuleName()) + } + } + } + + var coreVariantNeeded bool = false + var ramdiskVariantNeeded bool = false + var recoveryVariantNeeded bool = false + + var vendorVariants []string + var productVariants []string + + platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion() + boardVndkVersion := mctx.DeviceConfig().VndkVersion() + productVndkVersion := mctx.DeviceConfig().ProductVndkVersion() + if boardVndkVersion == "current" { + boardVndkVersion = platformVndkVersion + } + if productVndkVersion == "current" { + productVndkVersion = platformVndkVersion + } + + if boardVndkVersion == "" { + // If the device isn't compiling against the VNDK, we always + // use the core mode. + coreVariantNeeded = true + } else if _, ok := m.linker.(*llndkStubDecorator); ok { + // LL-NDK stubs only exist in the vendor and product variants, + // since the real libraries will be used in the core variant. + vendorVariants = append(vendorVariants, + platformVndkVersion, + boardVndkVersion, + ) + productVariants = append(productVariants, + platformVndkVersion, + productVndkVersion, + ) + } else if _, ok := m.linker.(*llndkHeadersDecorator); ok { + // ... and LL-NDK headers as well + vendorVariants = append(vendorVariants, + platformVndkVersion, + boardVndkVersion, + ) + productVariants = append(productVariants, + platformVndkVersion, + productVndkVersion, + ) + } else if m.isSnapshotPrebuilt() { + // Make vendor variants only for the versions in BOARD_VNDK_VERSION and + // PRODUCT_EXTRA_VNDK_VERSIONS. + if snapshot, ok := m.linker.(interface { + version() string + }); ok { + vendorVariants = append(vendorVariants, snapshot.version()) + } else { + mctx.ModuleErrorf("version is unknown for snapshot prebuilt") + } + } else if m.HasVendorVariant() && !m.isVndkExt() { + // This will be available in /system, /vendor and /product + // or a /system directory that is available to vendor and product. + coreVariantNeeded = true + + // We assume that modules under proprietary paths are compatible for + // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or + // PLATFORM_VNDK_VERSION. + if isVendorProprietaryPath(mctx.ModuleDir()) { + vendorVariants = append(vendorVariants, boardVndkVersion) + } else { + vendorVariants = append(vendorVariants, platformVndkVersion) + } + + // vendor_available modules are also available to /product. + productVariants = append(productVariants, platformVndkVersion) + // VNDK is always PLATFORM_VNDK_VERSION + if !m.IsVndk() { + productVariants = append(productVariants, productVndkVersion) + } + } else if vendorSpecific && String(m.Properties.Sdk_version) == "" { + // This will be available in /vendor (or /odm) only + + // kernel_headers is a special module type whose exported headers + // are coming from DeviceKernelHeaders() which is always vendor + // dependent. They'll always have both vendor variants. + // For other modules, we assume that modules under proprietary + // paths are compatible for BOARD_VNDK_VERSION. The other modules + // are regarded as AOSP, which is PLATFORM_VNDK_VERSION. + if _, ok := m.linker.(*kernelHeadersDecorator); ok { + vendorVariants = append(vendorVariants, + platformVndkVersion, + boardVndkVersion, + ) + } else if isVendorProprietaryPath(mctx.ModuleDir()) { + vendorVariants = append(vendorVariants, boardVndkVersion) + } else { + vendorVariants = append(vendorVariants, platformVndkVersion) + } + } else { + // This is either in /system (or similar: /data), or is a + // modules built with the NDK. Modules built with the NDK + // will be restricted using the existing link type checks. + coreVariantNeeded = true + } + + if boardVndkVersion != "" && productVndkVersion != "" { + if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" { + // The module has "product_specific: true" that does not create core variant. + coreVariantNeeded = false + productVariants = append(productVariants, productVndkVersion) + } + } else { + // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no + // restriction to use system libs. + // No product variants defined in this case. + productVariants = []string{} + } + + if Bool(m.Properties.Ramdisk_available) { + ramdiskVariantNeeded = true + } + + if m.ModuleBase.InstallInRamdisk() { + ramdiskVariantNeeded = true + coreVariantNeeded = false + } + + if Bool(m.Properties.Recovery_available) { + recoveryVariantNeeded = true + } + + if m.ModuleBase.InstallInRecovery() { + recoveryVariantNeeded = true + coreVariantNeeded = false + } + + for _, variant := range android.FirstUniqueStrings(vendorVariants) { + m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant) + } + + for _, variant := range android.FirstUniqueStrings(productVariants) { + m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant) + } + + m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded + m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded + m.Properties.CoreVariantNeeded = coreVariantNeeded +} + +func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool { + return c.Properties.CoreVariantNeeded +} + +func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { + return c.Properties.RamdiskVariantNeeded +} + +func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { + return c.Properties.RecoveryVariantNeeded +} + +func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string { + return c.Properties.ExtraVariants +} + +func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) { + m := module.(*Module) + if variant == android.RamdiskVariation { + m.MakeAsPlatform() + } else if variant == android.RecoveryVariation { + m.MakeAsPlatform() + squashRecoverySrcs(m) + } else if strings.HasPrefix(variant, VendorVariationPrefix) { + m.Properties.ImageVariationPrefix = VendorVariationPrefix + m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix) + squashVendorSrcs(m) + + // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION. + // Hide other vendor variants to avoid collision. + vndkVersion := ctx.DeviceConfig().VndkVersion() + if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion { + m.Properties.HideFromMake = true + m.SkipInstall() + } + } else if strings.HasPrefix(variant, ProductVariationPrefix) { + m.Properties.ImageVariationPrefix = ProductVariationPrefix + m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix) + squashVendorSrcs(m) + } +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 33e4a4abc..cd979cfad 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -57,9 +57,7 @@ var ( cfiAsflags = []string{"-flto", "-fvisibility=default"} cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi", "-Wl,-plugin-opt,O1"} - cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map" - cfiStaticLibsMutex sync.Mutex - hwasanStaticLibsMutex sync.Mutex + cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map" intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blocklist.txt"} @@ -1050,15 +1048,9 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { // Export the static lib name to make if c.static() && c.ExportedToMake() { if t == cfi { - appendStringSync(c.Name(), cfiStaticLibs(mctx.Config()), &cfiStaticLibsMutex) + cfiStaticLibs(mctx.Config()).add(c, c.Name()) } else if t == hwasan { - if c.UseVndk() { - appendStringSync(c.Name(), hwasanVendorStaticLibs(mctx.Config()), - &hwasanStaticLibsMutex) - } else { - appendStringSync(c.Name(), hwasanStaticLibs(mctx.Config()), - &hwasanStaticLibsMutex) - } + hwasanStaticLibs(mctx.Config()).add(c, c.Name()) } } } else { @@ -1088,34 +1080,74 @@ 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 + libsMapLock sync.Mutex + sanitizerType sanitizerType +} + +func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap { + return &sanitizerStaticLibsMap{ + sanitizerType: t, + 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() + + s.libsMapLock.Lock() + defer s.libsMapLock.Unlock() + + if _, ok := s.libsMap[image]; !ok { + s.libsMap[image] = make(map[string][]string) + } + + s.libsMap[image][arch] = append(s.libsMap[image][arch], name) +} + +// Exports makefile variables in the following format: +// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES +// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES +// These are to be used by use_soong_sanitized_static_libraries. +// 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)] + for _, arch := range android.SortedStringKeys(archMap) { + libs := archMap[arch] + sort.Strings(libs) + + key := fmt.Sprintf( + "SOONG_%s_%s_%s_STATIC_LIBRARIES", + s.sanitizerType.variationName(), + image, // already upper + arch) + + ctx.Strict(key, strings.Join(libs, " ")) + } + } +} + var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs") -func cfiStaticLibs(config android.Config) *[]string { +func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap { return config.Once(cfiStaticLibsKey, func() interface{} { - return &[]string{} - }).(*[]string) + return newSanitizerStaticLibsMap(cfi) + }).(*sanitizerStaticLibsMap) } var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs") -func hwasanStaticLibs(config android.Config) *[]string { +func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap { return config.Once(hwasanStaticLibsKey, func() interface{} { - return &[]string{} - }).(*[]string) -} - -var hwasanVendorStaticLibsKey = android.NewOnceKey("hwasanVendorStaticLibs") - -func hwasanVendorStaticLibs(config android.Config) *[]string { - return config.Once(hwasanVendorStaticLibsKey, func() interface{} { - return &[]string{} - }).(*[]string) -} - -func appendStringSync(item string, list *[]string, mutex *sync.Mutex) { - mutex.Lock() - *list = append(*list, item) - mutex.Unlock() + return newSanitizerStaticLibsMap(hwasan) + }).(*sanitizerStaticLibsMap) } func enableMinimalRuntime(sanitize *sanitize) bool { @@ -1145,17 +1177,9 @@ func enableUbsanRuntime(sanitize *sanitize) bool { } func cfiMakeVarsProvider(ctx android.MakeVarsContext) { - cfiStaticLibs := cfiStaticLibs(ctx.Config()) - sort.Strings(*cfiStaticLibs) - ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " ")) + cfiStaticLibs(ctx.Config()).exportToMake(ctx) } func hwasanMakeVarsProvider(ctx android.MakeVarsContext) { - hwasanStaticLibs := hwasanStaticLibs(ctx.Config()) - sort.Strings(*hwasanStaticLibs) - ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " ")) - - hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config()) - sort.Strings(*hwasanVendorStaticLibs) - ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " ")) + hwasanStaticLibs(ctx.Config()).exportToMake(ctx) }