From 49932f3e6975f5a39d8f9f5b064431d105740ada Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Fri, 9 Aug 2019 14:44:36 +0900 Subject: Build native coverage variant of APEXes when needed When the native coverage is enabled, APEXes (and files there) are built for native coverage as well. Bug: 138952487 Test: make -j NATIVE_COVERAGE=true COVERAGE_PATHS='*' com.android.resolv find out -name "*.gcno" | grep DnsResolver shows files Test: libnetd_resolv.zip is found under $(TARGET_OUT)/apex/com.android.resolv/lib directory Merged-In: I97bcee9bf8ffc0dc71453abbdb613ed56ea2cdb4 (cherry picked from commit ee9a98d88ec9a792c3d67b9aed9e4571bf2544cf) Change-Id: I97bcee9bf8ffc0dc71453abbdb613ed56ea2cdb4 --- apex/apex.go | 32 +++++++++++++++++++++++++++++--- cc/binary.go | 4 ++++ cc/cc.go | 8 ++++++++ cc/coverage.go | 18 +++++++++++++++++- cc/library.go | 4 ++++ cc/object.go | 4 ++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 69a50f1c..214ed086 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -266,6 +266,10 @@ type apexBundleProperties struct { // List of sanitizer names that this APEX is enabled for SanitizerNames []string `blueprint:"mutated"` + + PreventInstall bool `blueprint:"mutated"` + + HideFromMake bool `blueprint:"mutated"` } type apexTargetBundleProperties struct { @@ -548,7 +552,7 @@ func (a *apexBundle) Srcs() android.Paths { } func (a *apexBundle) installable() bool { - return a.properties.Installable == nil || proptools.Bool(a.properties.Installable) + return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable)) } func (a *apexBundle) getImageVariation(config android.DeviceConfig) string { @@ -583,6 +587,18 @@ func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizer return android.InList(sanitizerName, globalSanitizerNames) } +func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseContext) bool { + return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() +} + +func (a *apexBundle) PreventInstall() { + a.properties.PreventInstall = true +} + +func (a *apexBundle) HideFromMake() { + a.properties.HideFromMake = true +} + func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) { // Decide the APEX-local directory by the multilib of the library // In the future, we may query this to the module. @@ -1082,6 +1098,11 @@ func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { } func (a *apexBundle) AndroidMk() android.AndroidMkData { + if a.properties.HideFromMake { + return android.AndroidMkData{ + Disabled: true, + } + } writers := []android.AndroidMkData{} if a.apexTypes.image() { writers = append(writers, a.androidMkForType(imageApex)) @@ -1171,8 +1192,13 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apex fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk") } else if fi.class == nativeSharedLib || fi.class == nativeExecutable { fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) - if cc, ok := fi.module.(*cc.Module); ok && cc.UnstrippedOutputFile() != nil { - fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String()) + if cc, ok := fi.module.(*cc.Module); ok { + if cc.UnstrippedOutputFile() != nil { + fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String()) + } + if cc.CoverageOutputFile().Valid() { + fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", cc.CoverageOutputFile().String()) + } } fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk") } else { diff --git a/cc/binary.go b/cc/binary.go index 666e8849..d7d7e4f0 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -421,6 +421,10 @@ func (binary *binaryDecorator) nativeCoverage() bool { return true } +func (binary *binaryDecorator) coverageOutputFilePath() android.OptionalPath { + return binary.coverageOutputFile +} + // /system/bin/linker -> /apex/com.android.runtime/bin/linker func (binary *binaryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, file android.Path) { dir := binary.baseInstaller.installDir(ctx) diff --git a/cc/cc.go b/cc/cc.go index 0668fd9a..89beee49 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -311,6 +311,7 @@ type linker interface { unstrippedOutputFilePath() android.Path nativeCoverage() bool + coverageOutputFilePath() android.OptionalPath } type installer interface { @@ -419,6 +420,13 @@ func (c *Module) UnstrippedOutputFile() android.Path { return nil } +func (c *Module) CoverageOutputFile() android.OptionalPath { + if c.linker != nil { + return c.linker.coverageOutputFilePath() + } + return android.OptionalPath{} +} + func (c *Module) RelativeInstallPath() string { if c.installer != nil { return c.installer.relativeInstallPath() diff --git a/cc/coverage.go b/cc/coverage.go index 9dc7f06b..f4f8a049 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -138,7 +138,6 @@ func (cov *coverage) begin(ctx BaseModuleContext) { } else { // Check if Native_coverage is set to false. This property defaults to true. needCoverageVariant = BoolDefault(cov.Properties.Native_coverage, true) - if sdk_version := ctx.sdkVersion(); ctx.useSdk() && sdk_version != "current" { // Native coverage is not supported for SDK versions < 23 if fromApi, err := strconv.Atoi(sdk_version); err == nil && fromApi < 23 { @@ -156,6 +155,14 @@ func (cov *coverage) begin(ctx BaseModuleContext) { cov.Properties.NeedCoverageVariant = needCoverageVariant } +// Coverage is an interface for non-CC modules to implement to be mutated for coverage +type Coverage interface { + android.Module + IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool + PreventInstall() + HideFromMake() +} + func coverageMutator(mctx android.BottomUpMutatorContext) { if c, ok := mctx.Module().(*Module); ok && c.coverage != nil { needCoverageVariant := c.coverage.Properties.NeedCoverageVariant @@ -175,5 +182,14 @@ func coverageMutator(mctx android.BottomUpMutatorContext) { m[1].(*Module).coverage.Properties.CoverageEnabled = needCoverageBuild m[1].(*Module).coverage.Properties.IsCoverageVariant = true } + } else if cov, ok := mctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(mctx) { + // APEX modules fall here + + // Note: variant "" is also created because an APEX can be depended on by another + // module which are split into "" and "cov" variants. e.g. when cc_test refers + // to an APEX via 'data' property. + m := mctx.CreateVariations("", "cov") + m[0].(Coverage).PreventInstall() + m[0].(Coverage).HideFromMake() } } diff --git a/cc/library.go b/cc/library.go index ca1c1be0..1f4b8148 100644 --- a/cc/library.go +++ b/cc/library.go @@ -758,6 +758,10 @@ func (library *libraryDecorator) nativeCoverage() bool { return true } +func (library *libraryDecorator) coverageOutputFilePath() android.OptionalPath { + return library.coverageOutputFile +} + func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path { isLlndk := inList(ctx.baseModuleName(), llndkLibraries) || inList(ctx.baseModuleName(), ndkMigratedLibs) diff --git a/cc/object.go b/cc/object.go index 50ecc38e..2fefd301 100644 --- a/cc/object.go +++ b/cc/object.go @@ -118,3 +118,7 @@ func (object *objectLinker) unstrippedOutputFilePath() android.Path { func (object *objectLinker) nativeCoverage() bool { return true } + +func (object *objectLinker) coverageOutputFilePath() android.OptionalPath { + return android.OptionalPath{} +} -- cgit v1.2.3 From baa54c6ed830a7cd1cb7fe5405c7a33b65c9a2cc Mon Sep 17 00:00:00 2001 From: Oliver Nguyen Date: Wed, 24 Apr 2019 14:22:25 -0700 Subject: Package coverage files as a zip. Bug: 148178774 Test: make NATIVE_COVERAGE=true COVERAGE_PATHS="*" Change-Id: I955212a20ea19c854ebc88635252a1d174ea8f7f Merged-In: I955212a20ea19c854ebc88635252a1d174ea8f7f (cherry picked from commit c743414d4298c2ffad94eb4fc00d644b992b0bf8) --- cc/binary.go | 2 +- cc/builder.go | 23 +++++++++++++++++++---- cc/library.go | 4 ++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cc/binary.go b/cc/binary.go index 666e8849..f6510a45 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -388,7 +388,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext, objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...) objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...) - binary.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, binary.getStem(ctx)) + binary.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, binary.getStem(ctx)) // Need to determine symlinks early since some targets (ie APEX) need this // information but will not call 'install' diff --git a/cc/builder.go b/cc/builder.go index fc5400c7..a9ee4e92 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -227,6 +227,14 @@ var ( blueprint.RuleParams{ Command: "gunzip -c $in > $out", }) + + zip = pctx.AndroidStaticRule("zip", + blueprint.RuleParams{ + Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp", + CommandDeps: []string{"${SoongZipCmd}"}, + Rspfile: "$out.rsp", + RspfileContent: "$in", + }) ) func init() { @@ -239,6 +247,8 @@ func init() { // Darwin doesn't have /proc pctx.StaticVariable("relPwd", "") } + + pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") } type builderFlags struct { @@ -867,13 +877,18 @@ func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path, }) } -func TransformCoverageFilesToLib(ctx android.ModuleContext, - inputs Objects, flags builderFlags, baseName string) android.OptionalPath { +func TransformCoverageFilesToZip(ctx android.ModuleContext, + inputs Objects, baseName string) android.OptionalPath { if len(inputs.coverageFiles) > 0 { - outputFile := android.PathForModuleOut(ctx, baseName+".gcnodir") + outputFile := android.PathForModuleOut(ctx, baseName+".zip") - TransformObjToStaticLib(ctx, inputs.coverageFiles, flags, outputFile, nil) + ctx.Build(pctx, android.BuildParams{ + Rule: zip, + Description: "zip " + outputFile.Base(), + Inputs: inputs.coverageFiles, + Output: outputFile, + }) return android.OptionalPathForPath(outputFile) } diff --git a/cc/library.go b/cc/library.go index ca1c1be0..2b340508 100644 --- a/cc/library.go +++ b/cc/library.go @@ -629,7 +629,7 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles) - library.coverageOutputFile = TransformCoverageFilesToLib(ctx, library.objects, builderFlags, + library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName()+library.MutatedProperties.VariantName) library.wholeStaticMissingDeps = ctx.GetMissingDependencies() @@ -741,7 +741,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...) objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...) - library.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, library.getLibName(ctx)) + library.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, library.getLibName(ctx)) library.linkSAbiDumpFiles(ctx, objs, fileName, ret) return ret -- cgit v1.2.3 From 2363a2b162cac1946ae4a8677a473890da98dc10 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Tue, 2 Jul 2019 14:55:35 -0700 Subject: Refactor libprofile-extras to be added as a whole static library Bug: http://b/134177005 Bug: http://b/116873221 Previously, the libprofile-extras dependency was added as a LateStaticLib and the constructor in this library was included during linking with the '-uinit_profile_extras' linker flag. This was done because at the deps() stage, the exact binaries that need coverage are not known (in fact the coverage-enabled variants are not created yet). This meant that for a link command, if one of the shared libraries already exported the constructor, the output of the link command did not load/link libprofile-extras. For other reasons, we now want to add more symbols to this library that need to be linked into all libraries and executables. To accomplish that, refactor the dependency handling so libprofile-extras can be added as a 'WholeStaticLib'. This is done by creating a new dependency type (with a coverageDepTag dependency tag) to add libprofile-extras as a dependency for all modules that can potentially link with coverage. During the flags() call, this dependency is moved as a WholeStaticLib dependency iff coverage is enabled in this link step. There are a few NFC changes as well: - deps() takes a DepsContext parameter. - flags() has an extra PathDeps parameter and return value. - add useSdk() helper to cc.Module. Test: Build with coverage and check that we can generate coverage using SIGUSR1 and the debug.coverage.flush sysprop. Change-Id: I7e7d8201956a150febbda5bb1794f8ece016db8b Merged-In: I7e7d8201956a150febbda5bb1794f8ece016db8b (cherry picked from commit 82fe59b65684462cb70a17145336e54c3fe5c79c) --- cc/cc.go | 3 ++- cc/coverage.go | 44 ++++++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index 0668fd9a..c5b24a4f 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -357,6 +357,7 @@ var ( ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true} vndkExtDepTag = dependencyTag{name: "vndk extends", library: true} runtimeDepTag = dependencyTag{name: "runtime lib"} + coverageDepTag = dependencyTag{name: "coverage"} ) // Module contains the properties and members used by all C/C++ module types, and implements @@ -938,7 +939,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { flags = c.sanitize.flags(ctx, flags) } if c.coverage != nil { - flags = c.coverage.flags(ctx, flags) + flags, deps = c.coverage.flags(ctx, flags, deps) } if c.lto != nil { flags = c.lto.flags(ctx, flags) diff --git a/cc/coverage.go b/cc/coverage.go index 9dc7f06b..c189398a 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -17,6 +17,8 @@ package cc import ( "strconv" + "github.com/google/blueprint" + "android/soong/android" ) @@ -41,30 +43,28 @@ func (cov *coverage) props() []interface{} { return []interface{}{&cov.Properties} } -func (cov *coverage) deps(ctx BaseModuleContext, deps Deps) Deps { - if cov.Properties.NeedCoverageBuild { - // Link libprofile-extras/libprofile-extras_ndk when coverage - // variant is required. This is a no-op unless coverage is - // actually enabled during linking, when - // '-uinit_profile_extras' is added (in flags()) to force the - // setup code in libprofile-extras be linked into the - // binary/library. - // - // We cannot narrow it further to only the 'cov' variant since - // the mutator hasn't run (and we don't have the 'cov' variant - // yet). - if !ctx.useSdk() { - deps.LateStaticLibs = append(deps.LateStaticLibs, "libprofile-extras") - } else { - deps.LateStaticLibs = append(deps.LateStaticLibs, "libprofile-extras_ndk") - } +func getProfileLibraryName(ctx ModuleContextIntf) string { + // This function should only ever be called for a cc.Module, so the + // following statement should always succeed. + if ctx.useSdk() { + return "libprofile-extras_ndk" + } else { + return "libprofile-extras" + } +} + +func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps { + if cov.Properties.NeedCoverageVariant { + ctx.AddVariationDependencies([]blueprint.Variation{ + {Mutator: "link", Variation: "static"}, + }, coverageDepTag, getProfileLibraryName(ctx)) } return deps } -func (cov *coverage) flags(ctx ModuleContext, flags Flags) Flags { +func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) { if !ctx.DeviceConfig().NativeCoverageEnabled() { - return flags + return flags, deps } if cov.Properties.CoverageEnabled { @@ -114,11 +114,11 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags) Flags { if cov.linkCoverage { flags.LdFlags = append(flags.LdFlags, "--coverage") - // Force linking of constructor/setup code in libprofile-extras - flags.LdFlags = append(flags.LdFlags, "-uinit_profile_extras") + coverage := ctx.GetDirectDepWithTag(getProfileLibraryName(ctx), coverageDepTag).(*Module) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) } - return flags + return flags, deps } func (cov *coverage) begin(ctx BaseModuleContext) { -- cgit v1.2.3 From c2cf2c5dbe777e67d0dfc9f3130c265c81dd6198 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Tue, 2 Jul 2019 23:47:35 -0700 Subject: Wrap getenv when linking a coverage-enabled binary The wrapper to getenv() appends the effective userid (euid) of the current process to GCOV_PREFIX. This avoids conflicts and permissions issues when multiple processes try to create/access the same directories and files under /data/misc/trace. Bug: 148178774 Test: Verify that coverage files are written to /data/misc/trace//proc/... instead of /data/misc/trace/proc/... Change-Id: If58081a12b2b9bc40cfcbf64c99beafe198d07af Merged-In: If58081a12b2b9bc40cfcbf64c99beafe198d07af (cherry picked from commit 100bbdc8f3458b8a48b339356130cf4165aaadea) --- cc/coverage.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cc/coverage.go b/cc/coverage.go index c189398a..0de0c1c9 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -116,6 +116,8 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags coverage := ctx.GetDirectDepWithTag(getProfileLibraryName(ctx), coverageDepTag).(*Module) deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) + + flags.LdFlags = append(flags.LdFlags, "-Wl,--wrap,getenv") } return flags, deps -- cgit v1.2.3