Merge "Migrate sanitizers to transition mutators." am: 5ad0185b63
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2123434 Change-Id: I23330872d07c05465868a1eba56186846ceb246b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
c0d25950f2
6 changed files with 354 additions and 210 deletions
|
@ -93,6 +93,7 @@ type RegisterMutatorsContext interface {
|
|||
TopDown(name string, m TopDownMutator) MutatorHandle
|
||||
BottomUp(name string, m BottomUpMutator) MutatorHandle
|
||||
BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle
|
||||
Transition(name string, m TransitionMutator)
|
||||
}
|
||||
|
||||
type RegisterMutatorFunc func(RegisterMutatorsContext)
|
||||
|
@ -421,6 +422,124 @@ func (x *registerMutatorsContext) BottomUpBlueprint(name string, m blueprint.Bot
|
|||
return mutator
|
||||
}
|
||||
|
||||
type IncomingTransitionContext interface {
|
||||
// Module returns the target of the dependency edge for which the transition
|
||||
// is being computed
|
||||
Module() Module
|
||||
|
||||
// Config returns the configuration for the build.
|
||||
Config() Config
|
||||
}
|
||||
|
||||
type OutgoingTransitionContext interface {
|
||||
// Module returns the target of the dependency edge for which the transition
|
||||
// is being computed
|
||||
Module() Module
|
||||
|
||||
// DepTag() Returns the dependency tag through which this dependency is
|
||||
// reached
|
||||
DepTag() blueprint.DependencyTag
|
||||
}
|
||||
type TransitionMutator interface {
|
||||
// Split returns the set of variations that should be created for a module no
|
||||
// matter who depends on it. Used when Make depends on a particular variation
|
||||
// or when the module knows its variations just based on information given to
|
||||
// it in the Blueprint file. This method should not mutate the module it is
|
||||
// called on.
|
||||
Split(ctx BaseModuleContext) []string
|
||||
|
||||
// OutCalled on a module to determine which variation it wants from its direct
|
||||
// dependencies. The dependency itself can override this decision. This method
|
||||
// should not mutate the module itself.
|
||||
OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
|
||||
|
||||
// Called on a module to determine which variation it should be in based on
|
||||
// the variation modules that depend on it want. This gives the module a final
|
||||
// say about its own variations. This method should not mutate the module
|
||||
// itself.
|
||||
IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
|
||||
|
||||
// Called after a module was split into multiple variations on each variation.
|
||||
// It should not split the module any further but adding new dependencies is
|
||||
// fine. Unlike all the other methods on TransitionMutator, this method is
|
||||
// allowed to mutate the module.
|
||||
Mutate(ctx BottomUpMutatorContext, variation string)
|
||||
}
|
||||
|
||||
type androidTransitionMutator struct {
|
||||
finalPhase bool
|
||||
bazelConversionMode bool
|
||||
mutator TransitionMutator
|
||||
}
|
||||
|
||||
func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
|
||||
if m, ok := ctx.Module().(Module); ok {
|
||||
moduleContext := m.base().baseModuleContextFactory(ctx)
|
||||
moduleContext.bazelConversionMode = a.bazelConversionMode
|
||||
return a.mutator.Split(&moduleContext)
|
||||
} else {
|
||||
return []string{""}
|
||||
}
|
||||
}
|
||||
|
||||
type outgoingTransitionContextImpl struct {
|
||||
bp blueprint.OutgoingTransitionContext
|
||||
}
|
||||
|
||||
func (c *outgoingTransitionContextImpl) Module() Module {
|
||||
return c.bp.Module().(Module)
|
||||
}
|
||||
|
||||
func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag {
|
||||
return c.bp.DepTag()
|
||||
}
|
||||
|
||||
func (a *androidTransitionMutator) OutgoingTransition(ctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
|
||||
if _, ok := ctx.Module().(Module); ok {
|
||||
return a.mutator.OutgoingTransition(&outgoingTransitionContextImpl{bp: ctx}, sourceVariation)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type incomingTransitionContextImpl struct {
|
||||
bp blueprint.IncomingTransitionContext
|
||||
}
|
||||
|
||||
func (c *incomingTransitionContextImpl) Module() Module {
|
||||
return c.bp.Module().(Module)
|
||||
}
|
||||
|
||||
func (c *incomingTransitionContextImpl) Config() Config {
|
||||
return c.bp.Config().(Config)
|
||||
}
|
||||
|
||||
func (a *androidTransitionMutator) IncomingTransition(ctx blueprint.IncomingTransitionContext, incomingVariation string) string {
|
||||
if _, ok := ctx.Module().(Module); ok {
|
||||
return a.mutator.IncomingTransition(&incomingTransitionContextImpl{bp: ctx}, incomingVariation)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
|
||||
if am, ok := ctx.Module().(Module); ok {
|
||||
a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase, a.bazelConversionMode), variation)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) {
|
||||
atm := &androidTransitionMutator{
|
||||
finalPhase: x.finalPhase,
|
||||
bazelConversionMode: x.bazelConversionMode,
|
||||
mutator: m,
|
||||
}
|
||||
mutator := &mutator{
|
||||
name: name,
|
||||
transitionMutator: atm}
|
||||
x.mutators = append(x.mutators, mutator)
|
||||
}
|
||||
|
||||
func (x *registerMutatorsContext) mutatorName(name string) string {
|
||||
if x.bazelConversionMode {
|
||||
return name + "_bp2build"
|
||||
|
@ -456,6 +575,8 @@ func (mutator *mutator) register(ctx *Context) {
|
|||
handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
|
||||
} else if mutator.topDownMutator != nil {
|
||||
handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
|
||||
} else if mutator.transitionMutator != nil {
|
||||
blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
|
||||
}
|
||||
if mutator.parallel {
|
||||
handle.Parallel()
|
||||
|
|
|
@ -96,10 +96,11 @@ var singletons sortableComponents
|
|||
var preSingletons sortableComponents
|
||||
|
||||
type mutator struct {
|
||||
name string
|
||||
bottomUpMutator blueprint.BottomUpMutator
|
||||
topDownMutator blueprint.TopDownMutator
|
||||
parallel bool
|
||||
name string
|
||||
bottomUpMutator blueprint.BottomUpMutator
|
||||
topDownMutator blueprint.TopDownMutator
|
||||
transitionMutator blueprint.TransitionMutator
|
||||
parallel bool
|
||||
}
|
||||
|
||||
var _ sortableComponent = &mutator{}
|
||||
|
|
1
cc/cc.go
1
cc/cc.go
|
@ -990,6 +990,7 @@ func (c *Module) Shared() bool {
|
|||
return library.shared()
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("Shared() called on non-library module: %q", c.BaseModuleName()))
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,6 @@ type PlatformSanitizeable interface {
|
|||
// than left undefined.
|
||||
IsSanitizerExplicitlyDisabled(t SanitizerType) bool
|
||||
|
||||
// SanitizeDep returns true if the module is statically linked into another that is sanitized
|
||||
// with the given sanitizer.
|
||||
SanitizeDep(t SanitizerType) bool
|
||||
|
||||
// SetSanitizeDep marks a module as a static dependency of another module to be sanitized.
|
||||
SetSanitizeDep(t SanitizerType)
|
||||
|
||||
// SetSanitizer enables or disables the specified sanitizer type if it's supported, otherwise this should panic.
|
||||
SetSanitizer(t SanitizerType, b bool)
|
||||
|
||||
|
|
407
cc/sanitize.go
407
cc/sanitize.go
|
@ -153,9 +153,10 @@ func (t SanitizerType) name() string {
|
|||
|
||||
func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
|
||||
switch t {
|
||||
case Asan, Hwasan, Fuzzer, scs, tsan, cfi:
|
||||
ctx.TopDown(t.variationName()+"_deps", sanitizerDepsMutator(t))
|
||||
ctx.BottomUp(t.variationName(), sanitizerMutator(t))
|
||||
case cfi, Hwasan, Asan, tsan, Fuzzer, scs:
|
||||
sanitizer := &sanitizerSplitMutator{t}
|
||||
ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
|
||||
ctx.Transition(t.variationName(), sanitizer)
|
||||
case Memtag_heap, intOverflow:
|
||||
// do nothing
|
||||
default:
|
||||
|
@ -276,7 +277,6 @@ type SanitizeUserProps struct {
|
|||
type SanitizeProperties struct {
|
||||
Sanitize SanitizeUserProps `android:"arch_variant"`
|
||||
SanitizerEnabled bool `blueprint:"mutated"`
|
||||
SanitizeDepTypes []SanitizerType `blueprint:"mutated"`
|
||||
MinimalRuntimeDep bool `blueprint:"mutated"`
|
||||
BuiltinsDep bool `blueprint:"mutated"`
|
||||
UbsanRuntimeDep bool `blueprint:"mutated"`
|
||||
|
@ -898,7 +898,7 @@ func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
|
|||
// 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.
|
||||
func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
|
||||
func needsCfiForVendorSnapshot(mctx android.BaseModuleContext) bool {
|
||||
if snapshot.IsVendorProprietaryModule(mctx) {
|
||||
return false
|
||||
}
|
||||
|
@ -926,62 +926,232 @@ func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
|
|||
!c.IsSanitizerExplicitlyDisabled(cfi)
|
||||
}
|
||||
|
||||
// Propagate sanitizer requirements down from binaries
|
||||
func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
|
||||
return func(mctx android.TopDownMutatorContext) {
|
||||
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.
|
||||
type sanitizerSplitMutator struct {
|
||||
sanitizer SanitizerType
|
||||
}
|
||||
|
||||
// If an APEX is sanitized or not depends on whether it contains at least one
|
||||
// sanitized module. Transition mutators cannot propagate information up the
|
||||
// dependency graph this way, so we need an auxiliary mutator to do so.
|
||||
func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDownMutatorContext) {
|
||||
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) {
|
||||
enabled = true
|
||||
c.SetSanitizeDep(t)
|
||||
}
|
||||
if enabled {
|
||||
isSanitizableDependencyTag := c.SanitizableDepTagChecker()
|
||||
mctx.WalkDeps(func(child, parent android.Module) bool {
|
||||
if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
|
||||
return false
|
||||
}
|
||||
if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
|
||||
!d.SanitizeNever() &&
|
||||
!d.IsSanitizerExplicitlyDisabled(t) {
|
||||
if t == cfi || t == Hwasan || t == scs || t == Asan {
|
||||
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(t)
|
||||
}
|
||||
} else {
|
||||
d.SetSanitizeDep(t)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
if enabled {
|
||||
sanitizeable.EnableSanitizer(s.sanitizer.name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
|
||||
if c, ok := ctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
|
||||
if s.sanitizer == cfi && needsCfiForVendorSnapshot(ctx) {
|
||||
return []string{"", s.sanitizer.variationName()}
|
||||
}
|
||||
|
||||
// If the given sanitizer is not requested in the .bp file for a module, it
|
||||
// won't automatically build the sanitized variation.
|
||||
if !c.IsSanitizerEnabled(s.sanitizer) {
|
||||
return []string{""}
|
||||
}
|
||||
|
||||
if c.Binary() {
|
||||
// If a sanitizer is enabled for a binary, we do not build the version
|
||||
// without the sanitizer
|
||||
return []string{s.sanitizer.variationName()}
|
||||
} else if c.StaticallyLinked() || c.Header() {
|
||||
// For static libraries, we build both versions. Some Make modules
|
||||
// apparently depend on this behavior.
|
||||
return []string{"", s.sanitizer.variationName()}
|
||||
} else {
|
||||
// We only build the requested variation of dynamic libraries
|
||||
return []string{s.sanitizer.variationName()}
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := ctx.Module().(JniSanitizeable); ok {
|
||||
// TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but
|
||||
// that is short-circuited for now
|
||||
return []string{""}
|
||||
}
|
||||
|
||||
// If an APEX has a sanitized dependency, we build the APEX in the sanitized
|
||||
// variation. This is useful because such APEXes require extra dependencies.
|
||||
if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
|
||||
enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
|
||||
if enabled {
|
||||
return []string{s.sanitizer.variationName()}
|
||||
} else {
|
||||
return []string{""}
|
||||
}
|
||||
}
|
||||
|
||||
if c, ok := ctx.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 ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerEnabled(s.sanitizer) {
|
||||
return []string{"", s.sanitizer.variationName()}
|
||||
} else {
|
||||
return []string{""}
|
||||
}
|
||||
}
|
||||
|
||||
return []string{""}
|
||||
}
|
||||
|
||||
func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
|
||||
if c, ok := ctx.Module().(PlatformSanitizeable); ok {
|
||||
if !c.SanitizableDepTagChecker()(ctx.DepTag()) {
|
||||
// If the dependency is through a non-sanitizable tag, use the
|
||||
// non-sanitized variation
|
||||
return ""
|
||||
}
|
||||
|
||||
return sourceVariation
|
||||
} else if _, ok := ctx.Module().(JniSanitizeable); ok {
|
||||
// TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but
|
||||
// that is short-circuited for now
|
||||
return ""
|
||||
} else {
|
||||
// Otherwise, do not rock the boat.
|
||||
return sourceVariation
|
||||
}
|
||||
}
|
||||
|
||||
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.isSanitizerEnabled(s.sanitizer) {
|
||||
return incomingVariation
|
||||
}
|
||||
} else if jniSanitizeable, ok := mctx.Module().(JniSanitizeable); ok {
|
||||
// If it's a Java module with native dependencies through jni,
|
||||
// set the sanitizer for them
|
||||
if jniSanitizeable.IsSanitizerEnabledForJni(mctx, t.name()) {
|
||||
mctx.VisitDirectDeps(func(child android.Module) {
|
||||
if c, ok := child.(PlatformSanitizeable); ok &&
|
||||
mctx.OtherModuleDependencyTag(child) == JniFuzzLibTag &&
|
||||
c.SanitizePropDefined() &&
|
||||
!c.SanitizeNever() &&
|
||||
!c.IsSanitizerExplicitlyDisabled(t) {
|
||||
c.SetSanitizeDep(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if !d.SanitizePropDefined() ||
|
||||
d.SanitizeNever() ||
|
||||
d.IsSanitizerExplicitlyDisabled(s.sanitizer) ||
|
||||
!d.SanitizerSupported(s.sanitizer) {
|
||||
// If a module opts out of a sanitizer, use its non-sanitized variation
|
||||
return ""
|
||||
}
|
||||
|
||||
// Binaries are always built in the variation they requested.
|
||||
if d.Binary() {
|
||||
if d.IsSanitizerEnabled(s.sanitizer) {
|
||||
return s.sanitizer.variationName()
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
|
||||
// If an APEX module includes a lib which is enabled for a sanitizer T, then
|
||||
// the APEX module is also enabled for the same sanitizer type.
|
||||
mctx.VisitDirectDeps(func(child android.Module) {
|
||||
if c, ok := child.(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
|
||||
sanitizeable.EnableSanitizer(t.name())
|
||||
}
|
||||
|
||||
// If a shared library requests to be sanitized, it will be built for that
|
||||
// sanitizer. Otherwise, some sanitizers propagate through shared library
|
||||
// dependency edges, some do not.
|
||||
if !d.StaticallyLinked() && !d.Header() {
|
||||
if d.IsSanitizerEnabled(s.sanitizer) {
|
||||
return s.sanitizer.variationName()
|
||||
}
|
||||
|
||||
if s.sanitizer == cfi || s.sanitizer == Hwasan || s.sanitizer == scs || s.sanitizer == Asan {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Static and header libraries inherit whether they are sanitized from the
|
||||
// module they are linked into
|
||||
return incomingVariation
|
||||
} else if d, ok := ctx.Module().(Sanitizeable); ok {
|
||||
// If an APEX contains a sanitized module, it will be built in the variation
|
||||
// corresponding to that sanitizer.
|
||||
enabled := d.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
|
||||
if enabled {
|
||||
return s.sanitizer.variationName()
|
||||
}
|
||||
|
||||
return incomingVariation
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, variationName string) {
|
||||
sanitizerVariation := variationName == s.sanitizer.variationName()
|
||||
|
||||
if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
|
||||
sanitizerEnabled := c.IsSanitizerEnabled(s.sanitizer)
|
||||
|
||||
oneMakeVariation := false
|
||||
if c.StaticallyLinked() || c.Header() {
|
||||
if s.sanitizer != cfi && s.sanitizer != scs && s.sanitizer != Hwasan {
|
||||
// These sanitizers export only one variation to Make. For the rest,
|
||||
// Make targets can depend on both the sanitized and non-sanitized
|
||||
// versions.
|
||||
oneMakeVariation = true
|
||||
}
|
||||
} else if !c.Binary() {
|
||||
// Shared library. These are the sanitizers that do propagate through shared
|
||||
// library dependencies and therefore can cause multiple variations of a
|
||||
// shared library to be built.
|
||||
if s.sanitizer != cfi && s.sanitizer != Hwasan && s.sanitizer != scs && s.sanitizer != Asan {
|
||||
oneMakeVariation = true
|
||||
}
|
||||
}
|
||||
|
||||
if oneMakeVariation {
|
||||
if sanitizerEnabled != sanitizerVariation {
|
||||
c.SetPreventInstall()
|
||||
c.SetHideFromMake()
|
||||
}
|
||||
}
|
||||
|
||||
if sanitizerVariation {
|
||||
c.SetSanitizer(s.sanitizer, true)
|
||||
|
||||
// CFI is incompatible with ASAN so disable it in ASAN variations
|
||||
if s.sanitizer.incompatibleWithCfi() {
|
||||
cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
|
||||
if mctx.Device() && cfiSupported {
|
||||
c.SetSanitizer(cfi, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// locate the asan libraries under /data/asan
|
||||
if !c.Binary() && !c.StaticallyLinked() && !c.Header() && mctx.Device() && s.sanitizer == Asan && sanitizerEnabled {
|
||||
c.SetInSanitizerDir()
|
||||
}
|
||||
|
||||
if c.StaticallyLinked() && c.ExportedToMake() {
|
||||
if s.sanitizer == Hwasan {
|
||||
hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
|
||||
} else if s.sanitizer == cfi {
|
||||
cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
|
||||
}
|
||||
}
|
||||
} else if c.IsSanitizerEnabled(s.sanitizer) {
|
||||
// Disable the sanitizer for the non-sanitized variation
|
||||
c.SetSanitizer(s.sanitizer, false)
|
||||
}
|
||||
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
|
||||
// If an APEX has sanitized dependencies, it gets a few more dependencies
|
||||
if sanitizerVariation {
|
||||
sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
|
||||
}
|
||||
} else if c, ok := mctx.Module().(*Module); ok {
|
||||
if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerEnabled(s.sanitizer) {
|
||||
c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation)
|
||||
|
||||
// Export the static lib name to make
|
||||
if c.static() && c.ExportedToMake() {
|
||||
if s.sanitizer == cfi {
|
||||
// use BaseModuleName which is the name for Make.
|
||||
cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1307,16 +1477,6 @@ func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
|
|||
return c.sanitize.isSanitizerEnabled(t)
|
||||
}
|
||||
|
||||
func (c *Module) SanitizeDep(t SanitizerType) bool {
|
||||
for _, e := range c.sanitize.Properties.SanitizeDepTypes {
|
||||
if t == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) StaticallyLinked() bool {
|
||||
return c.static()
|
||||
}
|
||||
|
@ -1333,123 +1493,8 @@ func (c *Module) SetSanitizer(t SanitizerType, b bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Module) SetSanitizeDep(t SanitizerType) {
|
||||
if !c.SanitizeDep(t) {
|
||||
c.sanitize.Properties.SanitizeDepTypes = append(c.sanitize.Properties.SanitizeDepTypes, t)
|
||||
}
|
||||
}
|
||||
|
||||
var _ PlatformSanitizeable = (*Module)(nil)
|
||||
|
||||
// Create sanitized variants for modules that need them
|
||||
func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
|
||||
return func(mctx android.BottomUpMutatorContext) {
|
||||
if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
|
||||
|
||||
// Make sure we're not setting CFI to any value if it's not supported.
|
||||
cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
|
||||
|
||||
if c.Binary() && c.IsSanitizerEnabled(t) {
|
||||
modules := mctx.CreateVariations(t.variationName())
|
||||
modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
|
||||
} else if c.IsSanitizerEnabled(t) || c.SanitizeDep(t) {
|
||||
isSanitizerEnabled := c.IsSanitizerEnabled(t)
|
||||
if c.StaticallyLinked() || c.Header() || 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
|
||||
// that isn't sanitized for asan/fuzzer.
|
||||
//
|
||||
// Note for defaultVariation: since we don't split for shared libs but for static/header
|
||||
// libs, it is possible for the sanitized variant of a static/header lib to depend
|
||||
// on non-sanitized variant of a shared lib. Such unfulfilled variation causes an
|
||||
// error when the module is split. defaultVariation is the name of the variation that
|
||||
// will be used when such a dangling dependency occurs during the split of the current
|
||||
// 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
|
||||
mctx.SetDefaultDependencyVariation(&defaultVariation)
|
||||
|
||||
modules := mctx.CreateVariations("", t.variationName())
|
||||
modules[0].(PlatformSanitizeable).SetSanitizer(t, false)
|
||||
modules[1].(PlatformSanitizeable).SetSanitizer(t, true)
|
||||
|
||||
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].(PlatformSanitizeable).SetSanitizer(cfi, false)
|
||||
}
|
||||
|
||||
// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
|
||||
// to Make, because the sanitized version has a different suffix in name.
|
||||
// For other types of sanitizers, suppress the variation that is disabled.
|
||||
if t != cfi && t != scs && t != Hwasan {
|
||||
if isSanitizerEnabled {
|
||||
modules[0].(PlatformSanitizeable).SetPreventInstall()
|
||||
modules[0].(PlatformSanitizeable).SetHideFromMake()
|
||||
} else {
|
||||
modules[1].(PlatformSanitizeable).SetPreventInstall()
|
||||
modules[1].(PlatformSanitizeable).SetHideFromMake()
|
||||
}
|
||||
}
|
||||
|
||||
// Export the static lib name to make
|
||||
if c.StaticallyLinked() && c.ExportedToMake() {
|
||||
if t == cfi {
|
||||
cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
|
||||
} else if t == Hwasan {
|
||||
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].(PlatformSanitizeable).SetSanitizer(t, true)
|
||||
|
||||
// locate the asan libraries under /data/asan
|
||||
if mctx.Device() && t == Asan && isSanitizerEnabled {
|
||||
modules[0].(PlatformSanitizeable).SetInSanitizerDir()
|
||||
}
|
||||
|
||||
if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
|
||||
// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
|
||||
// are incompatible with cfi
|
||||
modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx.Config(), t.name()) {
|
||||
// APEX fuzz modules fall here
|
||||
sanitizeable.AddSanitizerDependencies(mctx, t.name())
|
||||
mctx.CreateVariations(t.variationName())
|
||||
} else if _, ok := mctx.Module().(JniSanitizeable); ok {
|
||||
// Java fuzz modules fall here
|
||||
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.
|
||||
defaultVariation := t.variationName()
|
||||
mctx.SetDefaultDependencyVariation(&defaultVariation)
|
||||
modules := mctx.CreateVariations("", t.variationName())
|
||||
modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
|
||||
modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
|
||||
|
||||
// Export the static lib name to make
|
||||
if c.static() && c.ExportedToMake() {
|
||||
if t == cfi {
|
||||
// use BaseModuleName which is the name for Make.
|
||||
cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -49,8 +49,7 @@ type SanitizeProperties struct {
|
|||
Memtag_heap *bool `android:"arch_variant"`
|
||||
}
|
||||
}
|
||||
SanitizerEnabled bool `blueprint:"mutated"`
|
||||
SanitizeDepTypes []cc.SanitizerType `blueprint:"mutated"`
|
||||
SanitizerEnabled bool `blueprint:"mutated"`
|
||||
|
||||
// Used when we need to place libraries in their own directory, such as ASAN.
|
||||
InSanitizerDir bool `blueprint:"mutated"`
|
||||
|
@ -444,28 +443,12 @@ func (mod *Module) IsSanitizerExplicitlyDisabled(t cc.SanitizerType) bool {
|
|||
return mod.sanitize.isSanitizerExplicitlyDisabled(t)
|
||||
}
|
||||
|
||||
func (mod *Module) SanitizeDep(t cc.SanitizerType) bool {
|
||||
for _, e := range mod.sanitize.Properties.SanitizeDepTypes {
|
||||
if t == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (mod *Module) SetSanitizer(t cc.SanitizerType, b bool) {
|
||||
if !Bool(mod.sanitize.Properties.Sanitize.Never) {
|
||||
mod.sanitize.SetSanitizer(t, b)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Module) SetSanitizeDep(t cc.SanitizerType) {
|
||||
if !c.SanitizeDep(t) {
|
||||
c.sanitize.Properties.SanitizeDepTypes = append(c.sanitize.Properties.SanitizeDepTypes, t)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *Module) StaticallyLinked() bool {
|
||||
if lib, ok := mod.compiler.(libraryInterface); ok {
|
||||
return lib.rlib() || lib.static()
|
||||
|
|
Loading…
Reference in a new issue