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 = ""
if c.isSanitizerEnabled(cfi) {
if c.IsSanitizerEnabled(cfi) {
entries.SubName += ".cfi"
} else if c.isSanitizerEnabled(Hwasan) {
} else if c.IsSanitizerEnabled(Hwasan) {
entries.SubName += ".hwasan"
}

View file

@ -95,6 +95,18 @@ type Snapshottable interface {
// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
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.

View file

@ -1189,7 +1189,7 @@ func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDown
if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
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
}
})
@ -1243,12 +1243,10 @@ func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
}
}
if c, ok := ctx.Module().(*Module); ok {
//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
if c, ok := ctx.Module().(LinkableInterface); ok {
// Check if it's a snapshot module supporting sanitizer
if ss, ok := c.linker.(snapshotSanitizer); ok {
if ss.isSanitizerAvailable(s.sanitizer) {
if c.IsSnapshotSanitizer() {
if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
return []string{"", s.sanitizer.variationName()}
} else {
return []string{""}
@ -1280,8 +1278,8 @@ func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitio
func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
if d, ok := ctx.Module().(PlatformSanitizeable); ok {
if dm, ok := ctx.Module().(*Module); ok {
if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
if dm, ok := ctx.Module().(LinkableInterface); ok {
if dm.IsSnapshotSanitizerAvailable(s.sanitizer) {
return incomingVariation
}
}
@ -1396,19 +1394,19 @@ func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, vari
if sanitizerVariation {
sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
}
} else if c, ok := mctx.Module().(*Module); ok {
if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
if !ss.isUnsanitizedVariant() {
} else if c, ok := mctx.Module().(LinkableInterface); ok {
if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
if !c.IsSnapshotUnsanitizedVariant() {
// Snapshot sanitizer may have only one variantion.
// Skip exporting the module if it already has a sanitizer variation.
c.SetPreventInstall()
c.SetHideFromMake()
return
}
c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation)
c.SetSnapshotSanitizerVariation(s.sanitizer, sanitizerVariation)
// 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.
if s.sanitizer == cfi {
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 {
return Bool(c.sanitize.Properties.SanitizeMutated.Never)
}

View file

@ -403,11 +403,11 @@ type SnapshotLibraryProperties struct {
Sanitize_minimal_dep *bool `android:"arch_variant"`
}
type snapshotSanitizer interface {
isSanitizerAvailable(t SanitizerType) bool
setSanitizerVariation(t SanitizerType, enabled bool)
isSanitizerEnabled(t SanitizerType) bool
isUnsanitizedVariant() bool
type SnapshotSanitizer interface {
IsSanitizerAvailable(t SanitizerType) bool
SetSanitizerVariation(t SanitizerType, enabled bool)
IsSanitizerEnabled(t SanitizerType) bool
IsUnsanitizedVariant() bool
}
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)
}
if p.isSanitizerEnabled(cfi) {
if p.IsSanitizerEnabled(cfi) {
p.properties = p.sanitizerProperties.Cfi
} else if p.isSanitizerEnabled(Hwasan) {
} else if p.IsSanitizerEnabled(Hwasan) {
p.properties = p.sanitizerProperties.Hwasan
}
@ -526,9 +526,9 @@ func (p *snapshotLibraryDecorator) nativeCoverage() bool {
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 {
case cfi:
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) {
if !enabled || p.isSanitizerEnabled(t) {
func (p *snapshotLibraryDecorator) SetSanitizerVariation(t SanitizerType, enabled bool) {
if !enabled || p.IsSanitizerEnabled(t) {
return
}
if !p.isUnsanitizedVariant() {
if !p.IsUnsanitizedVariant() {
panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
}
p.sanitizerProperties.SanitizerVariation = t
}
func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool {
func (p *snapshotLibraryDecorator) IsSanitizerEnabled(t SanitizerType) bool {
return p.sanitizerProperties.SanitizerVariation == t
}
func (p *snapshotLibraryDecorator) isUnsanitizedVariant() bool {
return !p.isSanitizerEnabled(Asan) &&
!p.isSanitizerEnabled(Hwasan)
func (p *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
return !p.IsSanitizerEnabled(Asan) &&
!p.IsSanitizerEnabled(Hwasan)
}
func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {

View file

@ -54,11 +54,11 @@ var (
"-C symbol-mangling-version=v0",
"--color always",
"-Zdylib-lto",
"-Z link-native-libraries=no",
}
deviceGlobalRustFlags = []string{
"-C panic=abort",
"-Z link-native-libraries=no",
// Generate additional debug info for AutoFDO
"-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.location = InstallInData
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
return module, fuzz
}

View file

@ -15,6 +15,8 @@
package rust
import (
"fmt"
"android/soong/android"
"android/soong/cc"
@ -26,17 +28,80 @@ type snapshotLibraryDecorator struct {
*libraryDecorator
properties cc.SnapshotLibraryProperties
sanitizerProperties struct {
CfiEnabled bool `blueprint:"mutated"`
SanitizerVariation cc.SanitizerType `blueprint:"mutated"`
// Library flags for cfi variant.
Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
//TODO: Library flags for cfi variant when CFI is supported.
//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() {
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) {
cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
"vendor_snapshot_rlib", VendorSnapshotRlibFactory)
@ -81,6 +146,9 @@ func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags,
library.SetSnapshotAndroidMkSuffix(ctx, variant)
if library.IsSanitizerEnabled(cc.Hwasan) {
library.properties = library.sanitizerProperties.Hwasan
}
if !library.MatchesWithDevice(ctx.DeviceConfig()) {
return buildOutput{}
}