Merge "Propagate all sanitizer flags in SDK snapshots."
This commit is contained in:
@@ -221,10 +221,7 @@ var includeDirProperties = []includeDirsProperty{
|
||||
// Add properties that may, or may not, be arch specific.
|
||||
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
|
||||
|
||||
if libInfo.SanitizeNever {
|
||||
sanitizeSet := outputProperties.AddPropertySet("sanitize")
|
||||
sanitizeSet.AddProperty("never", true)
|
||||
}
|
||||
outputProperties.AddProperty("sanitize", &libInfo.Sanitize)
|
||||
|
||||
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
|
||||
if libInfo.outputFile != nil {
|
||||
@@ -373,8 +370,10 @@ type nativeLibInfoProperties struct {
|
||||
// not vary by arch so cannot be android specific.
|
||||
StubsVersion string `sdk:"ignored-on-host"`
|
||||
|
||||
// Value of SanitizeProperties.Sanitize.Never. Needs to be propagated for CRT objects.
|
||||
SanitizeNever bool `android:"arch_variant"`
|
||||
// Value of SanitizeProperties.Sanitize. Several - but not all - of these
|
||||
// affect the expanded variants. All are propagated to avoid entangling the
|
||||
// sanitizer logic with the snapshot generation.
|
||||
Sanitize SanitizeUserProps `android:"arch_variant"`
|
||||
|
||||
// outputFile is not exported as it is always arch specific.
|
||||
outputFile android.Path
|
||||
@@ -423,8 +422,8 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
|
||||
p.StubsVersion = ccModule.StubsVersion()
|
||||
}
|
||||
|
||||
if ccModule.sanitize != nil && proptools.Bool(ccModule.sanitize.Properties.Sanitize.Never) {
|
||||
p.SanitizeNever = true
|
||||
if ccModule.sanitize != nil {
|
||||
p.Sanitize = ccModule.sanitize.Properties.Sanitize
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -139,9 +139,7 @@ func (t sanitizerType) incompatibleWithCfi() bool {
|
||||
return t == asan || t == fuzzer || t == hwasan
|
||||
}
|
||||
|
||||
type SanitizeProperties struct {
|
||||
// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
|
||||
Sanitize struct {
|
||||
type SanitizeUserProps struct {
|
||||
Never *bool `android:"arch_variant"`
|
||||
|
||||
// main sanitizers
|
||||
@@ -179,8 +177,13 @@ type SanitizeProperties struct {
|
||||
|
||||
// value to pass to -fsanitize-blacklist
|
||||
Blocklist *string
|
||||
} `android:"arch_variant"`
|
||||
}
|
||||
|
||||
type SanitizeProperties struct {
|
||||
// Enable AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizer, and
|
||||
// others. Please see SanitizerUserProps in build/soong/cc/sanitize.go for
|
||||
// details.
|
||||
Sanitize SanitizeUserProps `android:"arch_variant"`
|
||||
SanitizerEnabled bool `blueprint:"mutated"`
|
||||
SanitizeDep bool `blueprint:"mutated"`
|
||||
MinimalRuntimeDep bool `blueprint:"mutated"`
|
||||
|
@@ -435,8 +435,10 @@ include/Test.h -> include/include/Test.h
|
||||
)
|
||||
}
|
||||
|
||||
// Verify that when the shared library has some common and some arch specific properties that the generated
|
||||
// snapshot is optimized properly.
|
||||
// Verify that when the shared library has some common and some arch specific
|
||||
// properties that the generated snapshot is optimized properly. Substruct
|
||||
// handling is tested with the sanitize clauses (but note there's a lot of
|
||||
// built-in logic in sanitize.go that can affect those flags).
|
||||
func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
|
||||
result := testSdkWithCc(t, `
|
||||
sdk {
|
||||
@@ -451,9 +453,18 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
|
||||
"aidl/foo/bar/Test.aidl",
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
sanitize: {
|
||||
fuzzer: false,
|
||||
integer_overflow: true,
|
||||
diag: { undefined: false },
|
||||
},
|
||||
arch: {
|
||||
arm64: {
|
||||
export_system_include_dirs: ["arm64/include"],
|
||||
sanitize: {
|
||||
hwaddress: true,
|
||||
integer_overflow: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
stl: "none",
|
||||
@@ -471,13 +482,26 @@ cc_prebuilt_library_shared {
|
||||
stl: "none",
|
||||
compile_multilib: "both",
|
||||
export_include_dirs: ["include/include"],
|
||||
sanitize: {
|
||||
fuzzer: false,
|
||||
diag: {
|
||||
undefined: false,
|
||||
},
|
||||
},
|
||||
arch: {
|
||||
arm64: {
|
||||
srcs: ["arm64/lib/mynativelib.so"],
|
||||
export_system_include_dirs: ["arm64/include/arm64/include"],
|
||||
sanitize: {
|
||||
hwaddress: true,
|
||||
integer_overflow: false,
|
||||
},
|
||||
},
|
||||
arm: {
|
||||
srcs: ["arm/lib/mynativelib.so"],
|
||||
sanitize: {
|
||||
integer_overflow: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -488,13 +512,26 @@ cc_prebuilt_library_shared {
|
||||
stl: "none",
|
||||
compile_multilib: "both",
|
||||
export_include_dirs: ["include/include"],
|
||||
sanitize: {
|
||||
fuzzer: false,
|
||||
diag: {
|
||||
undefined: false,
|
||||
},
|
||||
},
|
||||
arch: {
|
||||
arm64: {
|
||||
srcs: ["arm64/lib/mynativelib.so"],
|
||||
export_system_include_dirs: ["arm64/include/arm64/include"],
|
||||
sanitize: {
|
||||
hwaddress: true,
|
||||
integer_overflow: false,
|
||||
},
|
||||
},
|
||||
arm: {
|
||||
srcs: ["arm/lib/mynativelib.so"],
|
||||
sanitize: {
|
||||
integer_overflow: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -506,7 +543,7 @@ sdk_snapshot {
|
||||
`),
|
||||
checkAllCopyRules(`
|
||||
include/Test.h -> include/include/Test.h
|
||||
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
|
||||
.intermediates/mynativelib/android_arm64_armv8-a_shared_hwasan/mynativelib.so -> arm64/lib/mynativelib.so
|
||||
arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
|
||||
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
|
||||
)
|
||||
|
@@ -1346,7 +1346,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
|
||||
@@ -1383,18 +1384,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 != "" {
|
||||
@@ -1424,7 +1425,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 {
|
||||
@@ -1446,9 +1447,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,
|
||||
@@ -1512,7 +1519,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()
|
||||
|
Reference in New Issue
Block a user