rust: Rust sanitized snapshots variations

This adds support for correctly handling Rust sanitized snapshots,
ensuring they only have one variation.

The presence of multiple variations were causing build failures
when a rust_fuzz module for host was defined and a snapshot
build was requested.

This also sets -Z link-native-libraries=no on host modules
(in addition to device modules) to avoid emitting extra linkage
flags due to link attributes.

Bug: 282897366
Test: SOONG_SDK_SNAPSHOT_USE_SRCJAR=true m
Change-Id: Idf980c29145f11c530ad635a4eb5b01a1730ac24
This commit is contained in:
Ivan Lozano
2023-08-23 14:20:25 -04:00
parent 4e6c42d417
commit 5467a39984
7 changed files with 161 additions and 35 deletions

View File

@@ -530,9 +530,9 @@ func (c *snapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entrie
entries.SubName = "" entries.SubName = ""
if c.isSanitizerEnabled(cfi) { if c.IsSanitizerEnabled(cfi) {
entries.SubName += ".cfi" entries.SubName += ".cfi"
} else if c.isSanitizerEnabled(Hwasan) { } else if c.IsSanitizerEnabled(Hwasan) {
entries.SubName += ".hwasan" entries.SubName += ".hwasan"
} }

View File

@@ -95,6 +95,18 @@ type Snapshottable interface {
// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
IsSnapshotPrebuilt() bool IsSnapshotPrebuilt() bool
// IsSnapshotSanitizer returns true if this snapshot module implements SnapshotSanitizer.
IsSnapshotSanitizer() bool
// IsSnapshotSanitizerAvailable returns true if this snapshot module has a sanitizer source available (cfi, hwasan).
IsSnapshotSanitizerAvailable(t SanitizerType) bool
// SetSnapshotSanitizerVariation sets the sanitizer variation type for this snapshot module.
SetSnapshotSanitizerVariation(t SanitizerType, enabled bool)
// IsSnapshotUnsanitizedVariant returns true if this is the unsanitized snapshot module variant.
IsSnapshotUnsanitizedVariant() bool
} }
// LinkableInterface is an interface for a type of module that is linkable in a C++ library. // LinkableInterface is an interface for a type of module that is linkable in a C++ library.

View File

@@ -1189,7 +1189,7 @@ func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDown
if sanitizeable, ok := ctx.Module().(Sanitizeable); ok { if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name()) enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
ctx.VisitDirectDeps(func(dep android.Module) { ctx.VisitDirectDeps(func(dep android.Module) {
if c, ok := dep.(*Module); ok && c.sanitize.isSanitizerEnabled(s.sanitizer) { if c, ok := dep.(PlatformSanitizeable); ok && c.IsSanitizerEnabled(s.sanitizer) {
enabled = true enabled = true
} }
}) })
@@ -1243,12 +1243,10 @@ func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
} }
} }
if c, ok := ctx.Module().(*Module); ok { if c, ok := ctx.Module().(LinkableInterface); ok {
//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
// Check if it's a snapshot module supporting sanitizer // Check if it's a snapshot module supporting sanitizer
if ss, ok := c.linker.(snapshotSanitizer); ok { if c.IsSnapshotSanitizer() {
if ss.isSanitizerAvailable(s.sanitizer) { if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
return []string{"", s.sanitizer.variationName()} return []string{"", s.sanitizer.variationName()}
} else { } else {
return []string{""} return []string{""}
@@ -1280,8 +1278,8 @@ func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitio
func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
if d, ok := ctx.Module().(PlatformSanitizeable); ok { if d, ok := ctx.Module().(PlatformSanitizeable); ok {
if dm, ok := ctx.Module().(*Module); ok { if dm, ok := ctx.Module().(LinkableInterface); ok {
if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) { if dm.IsSnapshotSanitizerAvailable(s.sanitizer) {
return incomingVariation return incomingVariation
} }
} }
@@ -1396,19 +1394,19 @@ func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, vari
if sanitizerVariation { if sanitizerVariation {
sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name()) sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
} }
} else if c, ok := mctx.Module().(*Module); ok { } else if c, ok := mctx.Module().(LinkableInterface); ok {
if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) { if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
if !ss.isUnsanitizedVariant() { if !c.IsSnapshotUnsanitizedVariant() {
// Snapshot sanitizer may have only one variantion. // Snapshot sanitizer may have only one variantion.
// Skip exporting the module if it already has a sanitizer variation. // Skip exporting the module if it already has a sanitizer variation.
c.SetPreventInstall() c.SetPreventInstall()
c.SetHideFromMake() c.SetHideFromMake()
return return
} }
c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation) c.SetSnapshotSanitizerVariation(s.sanitizer, sanitizerVariation)
// Export the static lib name to make // Export the static lib name to make
if c.static() && c.ExportedToMake() { if c.Static() && c.ExportedToMake() {
// use BaseModuleName which is the name for Make. // use BaseModuleName which is the name for Make.
if s.sanitizer == cfi { if s.sanitizer == cfi {
cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName()) cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
@@ -1420,6 +1418,35 @@ func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, vari
} }
} }
func (c *Module) IsSnapshotSanitizer() bool {
if _, ok := c.linker.(SnapshotSanitizer); ok {
return true
}
return false
}
func (c *Module) IsSnapshotSanitizerAvailable(t SanitizerType) bool {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
return ss.IsSanitizerAvailable(t)
}
return false
}
func (c *Module) SetSnapshotSanitizerVariation(t SanitizerType, enabled bool) {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
ss.SetSanitizerVariation(t, enabled)
} else {
panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", c.Name()))
}
}
func (c *Module) IsSnapshotUnsanitizedVariant() bool {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
return ss.IsUnsanitizedVariant()
}
return false
}
func (c *Module) SanitizeNever() bool { func (c *Module) SanitizeNever() bool {
return Bool(c.sanitize.Properties.SanitizeMutated.Never) return Bool(c.sanitize.Properties.SanitizeMutated.Never)
} }

View File

@@ -403,11 +403,11 @@ type SnapshotLibraryProperties struct {
Sanitize_minimal_dep *bool `android:"arch_variant"` Sanitize_minimal_dep *bool `android:"arch_variant"`
} }
type snapshotSanitizer interface { type SnapshotSanitizer interface {
isSanitizerAvailable(t SanitizerType) bool IsSanitizerAvailable(t SanitizerType) bool
setSanitizerVariation(t SanitizerType, enabled bool) SetSanitizerVariation(t SanitizerType, enabled bool)
isSanitizerEnabled(t SanitizerType) bool IsSanitizerEnabled(t SanitizerType) bool
isUnsanitizedVariant() bool IsUnsanitizedVariant() bool
} }
type snapshotLibraryDecorator struct { type snapshotLibraryDecorator struct {
@@ -460,9 +460,9 @@ func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps Pat
return p.libraryDecorator.link(ctx, flags, deps, objs) return p.libraryDecorator.link(ctx, flags, deps, objs)
} }
if p.isSanitizerEnabled(cfi) { if p.IsSanitizerEnabled(cfi) {
p.properties = p.sanitizerProperties.Cfi p.properties = p.sanitizerProperties.Cfi
} else if p.isSanitizerEnabled(Hwasan) { } else if p.IsSanitizerEnabled(Hwasan) {
p.properties = p.sanitizerProperties.Hwasan p.properties = p.sanitizerProperties.Hwasan
} }
@@ -526,9 +526,9 @@ func (p *snapshotLibraryDecorator) nativeCoverage() bool {
return false return false
} }
var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil) var _ SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
func (p *snapshotLibraryDecorator) isSanitizerAvailable(t SanitizerType) bool { func (p *snapshotLibraryDecorator) IsSanitizerAvailable(t SanitizerType) bool {
switch t { switch t {
case cfi: case cfi:
return p.sanitizerProperties.Cfi.Src != nil return p.sanitizerProperties.Cfi.Src != nil
@@ -539,23 +539,23 @@ func (p *snapshotLibraryDecorator) isSanitizerAvailable(t SanitizerType) bool {
} }
} }
func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) { func (p *snapshotLibraryDecorator) SetSanitizerVariation(t SanitizerType, enabled bool) {
if !enabled || p.isSanitizerEnabled(t) { if !enabled || p.IsSanitizerEnabled(t) {
return return
} }
if !p.isUnsanitizedVariant() { if !p.IsUnsanitizedVariant() {
panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both")) panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
} }
p.sanitizerProperties.SanitizerVariation = t p.sanitizerProperties.SanitizerVariation = t
} }
func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool { func (p *snapshotLibraryDecorator) IsSanitizerEnabled(t SanitizerType) bool {
return p.sanitizerProperties.SanitizerVariation == t return p.sanitizerProperties.SanitizerVariation == t
} }
func (p *snapshotLibraryDecorator) isUnsanitizedVariant() bool { func (p *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
return !p.isSanitizerEnabled(Asan) && return !p.IsSanitizerEnabled(Asan) &&
!p.isSanitizerEnabled(Hwasan) !p.IsSanitizerEnabled(Hwasan)
} }
func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) { func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {

View File

@@ -54,11 +54,11 @@ var (
"-C symbol-mangling-version=v0", "-C symbol-mangling-version=v0",
"--color always", "--color always",
"-Zdylib-lto", "-Zdylib-lto",
"-Z link-native-libraries=no",
} }
deviceGlobalRustFlags = []string{ deviceGlobalRustFlags = []string{
"-C panic=abort", "-C panic=abort",
"-Z link-native-libraries=no",
// Generate additional debug info for AutoFDO // Generate additional debug info for AutoFDO
"-Z debug-info-for-profiling", "-Z debug-info-for-profiling",
} }

View File

@@ -60,6 +60,25 @@ func NewRustFuzz(hod android.HostOrDeviceSupported) (*Module, *fuzzDecorator) {
fuzz.binaryDecorator.baseCompiler.dir64 = "fuzz" fuzz.binaryDecorator.baseCompiler.dir64 = "fuzz"
fuzz.binaryDecorator.baseCompiler.location = InstallInData fuzz.binaryDecorator.baseCompiler.location = InstallInData
module.sanitize.SetSanitizer(cc.Fuzzer, true) module.sanitize.SetSanitizer(cc.Fuzzer, true)
// The fuzzer runtime is not present for darwin or bionic host modules, so disable rust_fuzz modules for these.
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
extraProps := struct {
Target struct {
Darwin struct {
Enabled *bool
}
Linux_bionic struct {
Enabled *bool
}
}
}{}
extraProps.Target.Darwin.Enabled = cc.BoolPtr(false)
extraProps.Target.Linux_bionic.Enabled = cc.BoolPtr(false)
ctx.AppendProperties(&extraProps)
})
module.compiler = fuzz module.compiler = fuzz
return module, fuzz return module, fuzz
} }

View File

@@ -15,6 +15,8 @@
package rust package rust
import ( import (
"fmt"
"android/soong/android" "android/soong/android"
"android/soong/cc" "android/soong/cc"
@@ -26,17 +28,80 @@ type snapshotLibraryDecorator struct {
*libraryDecorator *libraryDecorator
properties cc.SnapshotLibraryProperties properties cc.SnapshotLibraryProperties
sanitizerProperties struct { sanitizerProperties struct {
CfiEnabled bool `blueprint:"mutated"` SanitizerVariation cc.SanitizerType `blueprint:"mutated"`
// Library flags for cfi variant. //TODO: Library flags for cfi variant when CFI is supported.
Cfi cc.SnapshotLibraryProperties `android:"arch_variant"` //Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
// Library flags for hwasan variant.
Hwasan cc.SnapshotLibraryProperties `android:"arch_variant"`
} }
} }
var _ cc.SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
func (library *snapshotLibraryDecorator) IsSanitizerAvailable(t cc.SanitizerType) bool {
switch t {
//TODO: When CFI is supported, add a check here as well
case cc.Hwasan:
return library.sanitizerProperties.Hwasan.Src != nil
default:
return false
}
}
func (library *snapshotLibraryDecorator) SetSanitizerVariation(t cc.SanitizerType, enabled bool) {
if !enabled || library.IsSanitizerEnabled(t) {
return
}
if !library.IsUnsanitizedVariant() {
panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
}
library.sanitizerProperties.SanitizerVariation = t
}
func (library *snapshotLibraryDecorator) IsSanitizerEnabled(t cc.SanitizerType) bool {
return library.sanitizerProperties.SanitizerVariation == t
}
func (library *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
//TODO: When CFI is supported, add a check here as well
return !library.IsSanitizerEnabled(cc.Hwasan)
}
func init() { func init() {
registerRustSnapshotModules(android.InitRegistrationContext) registerRustSnapshotModules(android.InitRegistrationContext)
} }
func (mod *Module) IsSnapshotSanitizerAvailable(t cc.SanitizerType) bool {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return ss.IsSanitizerAvailable(t)
}
return false
}
func (mod *Module) SetSnapshotSanitizerVariation(t cc.SanitizerType, enabled bool) {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
ss.SetSanitizerVariation(t, enabled)
} else {
panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", mod.Name()))
}
}
func (mod *Module) IsSnapshotUnsanitizedVariant() bool {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return ss.IsUnsanitizedVariant()
}
return false
}
func (mod *Module) IsSnapshotSanitizer() bool {
if _, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return true
}
return false
}
func registerRustSnapshotModules(ctx android.RegistrationContext) { func registerRustSnapshotModules(ctx android.RegistrationContext) {
cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx, cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
"vendor_snapshot_rlib", VendorSnapshotRlibFactory) "vendor_snapshot_rlib", VendorSnapshotRlibFactory)
@@ -81,6 +146,9 @@ func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags,
library.SetSnapshotAndroidMkSuffix(ctx, variant) library.SetSnapshotAndroidMkSuffix(ctx, variant)
if library.IsSanitizerEnabled(cc.Hwasan) {
library.properties = library.sanitizerProperties.Hwasan
}
if !library.MatchesWithDevice(ctx.DeviceConfig()) { if !library.MatchesWithDevice(ctx.DeviceConfig()) {
return buildOutput{} return buildOutput{}
} }