Propagate all sanitizer flags in SDK snapshots.

liblog snapshot needs to sanitizer.address=false to avoid cycle in asan
builds. Adding that separately in library_sdk_member.go would start to
feel like whack-a-mole, so the snapshot generation is instead extended
to handle nested property structs.

This uses the BpPropertySet.AddProperty extension in
https://r.android.com/1423510, and common value optimisation now
recurses into non-anonymous structs, instead of comparing them as a
whole.

Test: m nothing
Test: `m SANITIZE_TARGET=address nothing` with prebuilts/runtime
  present in the manifest and a fresh snapshot made with this
Bug: 151303681
Change-Id: I472554117a488e6c800045cb2ed59377778571a4
This commit is contained in:
Martin Stjernholm
2020-09-15 02:32:35 +01:00
parent 191c25f589
commit b024957791
4 changed files with 112 additions and 65 deletions

View File

@@ -1348,7 +1348,8 @@ type isHostVariant interface {
// A property that can be optimized by the commonValueExtractor.
type extractorProperty struct {
// The name of the field for this property.
// The name of the field for this property. It is a "."-separated path for
// fields in non-anonymous substructs.
name string
// Filter that can use metadata associated with the properties being optimized
@@ -1385,18 +1386,18 @@ type commonValueExtractor struct {
func newCommonValueExtractor(propertiesStruct interface{}) *commonValueExtractor {
structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
extractor := &commonValueExtractor{}
extractor.gatherFields(structType, nil)
extractor.gatherFields(structType, nil, "")
return extractor
}
// Gather the fields from the supplied structure type from which common values will
// be extracted.
//
// This is recursive function. If it encounters an embedded field (no field name)
// that is a struct then it will recurse into that struct passing in the accessor
// for the field. That will then be used in the accessors for the fields in the
// embedded struct.
func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc) {
// This is recursive function. If it encounters a struct then it will recurse
// into it, passing in the accessor for the field and the struct name as prefix
// for the nested fields. That will then be used in the accessors for the fields
// in the embedded struct.
func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc, namePrefix string) {
for f := 0; f < structType.NumField(); f++ {
field := structType.Field(f)
if field.PkgPath != "" {
@@ -1426,7 +1427,7 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS
// Save a copy of the field index for use in the function.
fieldIndex := f
name := field.Name
name := namePrefix + field.Name
fieldGetter := func(value reflect.Value) reflect.Value {
if containingStructAccessor != nil {
@@ -1448,9 +1449,15 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS
return value.Field(fieldIndex)
}
if field.Type.Kind() == reflect.Struct && field.Anonymous {
// Gather fields from the embedded structure.
e.gatherFields(field.Type, fieldGetter)
if field.Type.Kind() == reflect.Struct {
// Gather fields from the nested or embedded structure.
var subNamePrefix string
if field.Anonymous {
subNamePrefix = namePrefix
} else {
subNamePrefix = name + "."
}
e.gatherFields(field.Type, fieldGetter, subNamePrefix)
} else {
property := extractorProperty{
name,
@@ -1514,7 +1521,8 @@ func (c dynamicMemberPropertiesContainer) String() string {
// Iterates over each exported field (capitalized name) and checks to see whether they
// have the same value (using DeepEquals) across all the input properties. If it does not then no
// change is made. Otherwise, the common value is stored in the field in the commonProperties
// and the field in each of the input properties structure is set to its default value.
// and the field in each of the input properties structure is set to its default value. Nested
// structs are visited recursively and their non-struct fields are compared.
func (e *commonValueExtractor) extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) error {
commonPropertiesValue := reflect.ValueOf(commonProperties)
commonStructValue := commonPropertiesValue.Elem()