Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  coverage.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cc

import (
 "strconv"

 "github.com/google/blueprint"

 "android/soong/android"
)

var (
 clangCoverageHostLdFlags = []string{
  "-Wl,--no-as-needed",
  "-Wl,--wrap,open",
 }
 clangContinuousCoverageFlags = []string{
  "-mllvm",
  "-runtime-counter-relocation",
 }
 clangCoverageCFlags = []string{
  "-Wno-frame-larger-than=",
 }
 clangCoverageCommonFlags = []string{
  "-fcoverage-mapping",
  "-Wno-pass-failed",
  "-D__ANDROID_CLANG_COVERAGE__",

  // Bug: http://b/408093589, http://b/396515430: LLVM change 4089763883 to
  // global merge regressed code coverage, marking previously covered lines
  // as uncovered.  Disable global merge until the regression is fixed.
  // -Wunused-command-line-argument needs to be disabled because
  // -mno-global-merge is reported as unused in LTO mode.
  "-mno-global-merge",
  "-Wno-unused-command-line-argument",
 }
 clangCoverageHWASanFlags = []string{
  "-mllvm",
  "-hwasan-globals=0",
 }
)

const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"

type CoverageProperties struct {
 Native_coverage *bool

 NeedCoverageVariant bool `blueprint:"mutated"`
 NeedCoverageBuild   bool `blueprint:"mutated"`

 CoverageEnabled   bool `blueprint:"mutated"`
 IsCoverageVariant bool `blueprint:"mutated"`
}

type coverage struct {
 Properties CoverageProperties

 // Whether binaries containing this module need --coverage added to their ldflags
 linkCoverage bool
}

func (cov *coverage) props() []interface{} {
 return []interface{}{&cov.Properties}
}

func getGcovProfileLibraryName(ctx ModuleContextIntf) string {
 // This function should only ever be called for a cc.Module, so the
 // following statement should always succeed.
 // LINT.IfChange
 if ctx.useSdk() {
  return "libprofile-extras_ndk"
 } else {
  return "libprofile-extras"
 }
}

func getClangProfileLibraryName(ctx ModuleContextIntf) string {
 if ctx.useSdk() {
  return "libprofile-clang-extras_ndk"
 } else if ctx.isCfiAssemblySupportEnabled() {
  return "libprofile-clang-extras_cfi_support"
 } else {
  return "libprofile-clang-extras"
 }
 // LINT.ThenChange(library.go)
}

func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
 if cov.Properties.NeedCoverageVariant && ctx.Device() {
  ctx.AddVariationDependencies([]blueprint.Variation{
   {Mutator: "link", Variation: "static"},
  }, CoverageDepTag, getGcovProfileLibraryName(ctx))
  ctx.AddVariationDependencies([]blueprint.Variation{
   {Mutator: "link", Variation: "static"},
  }, CoverageDepTag, getClangProfileLibraryName(ctx))
 }
 return deps
}

func EnableContinuousCoverage(ctx android.BaseModuleContext) bool {
 return ctx.DeviceConfig().ClangCoverageContinuousMode()
}

func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
 clangCoverage := ctx.DeviceConfig().ClangCoverageEnabled()
 gcovCoverage := ctx.DeviceConfig().GcovCoverageEnabled()

 if !gcovCoverage && !clangCoverage {
  return flags, deps
 }

 if cov.Properties.CoverageEnabled {
  cov.linkCoverage = true

  if gcovCoverage {
   flags.GcovCoverage = true
   flags.Local.CommonFlags = append(flags.Local.CommonFlags, "--coverage", "-O0")

   // Override -Wframe-larger-than and non-default optimization
   // flags that the module may use.
   flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0")
  } else if clangCoverage {
   flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag)
   flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangCoverageCommonFlags...)
   // Override -Wframe-larger-than.  We can expect frame size increase after
   // coverage instrumentation.
   flags.Local.CFlags = append(flags.Local.CFlags, clangCoverageCFlags...)
   if EnableContinuousCoverage(ctx) {
    flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangContinuousCoverageFlags...)
   }

   // http://b/248022906, http://b/247941801  enabling coverage and hwasan-globals
   // instrumentation together causes duplicate-symbol errors for __llvm_profile_filename.
   if c, ok := ctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(Hwasan) {
    flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangCoverageHWASanFlags...)
   }
  }
 }

 // Even if we don't have coverage enabled, if any of our object files were compiled
 // with coverage, then we need to add --coverage to our ldflags.
 if !cov.linkCoverage {
  if ctx.staticLibrary() {
   // For static libraries, the only thing that changes our object files
   // are included whole static libraries, so check to see if any of
   // those have coverage enabled.
   ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
    if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
     if depTag.static() && depTag.wholeStatic {
      if info, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider); ok {
       if info.LinkCoverage {
        cov.linkCoverage = true
       }
      }
     }
    }
   })
  } else {
   // For executables and shared libraries, we need to check all of
   // our static dependencies.
   ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
    if _, ok := android.OtherModuleProvider(ctx, m, StaticLibraryInfoProvider); ok {
     if info, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider); ok {
      if info.LinkCoverage {
       cov.linkCoverage = true
      }
     }
    }
   })
  }
 }

 if cov.linkCoverage {
  if gcovCoverage {
   flags.Local.LdFlags = append(flags.Local.LdFlags, "--coverage")

   if ctx.Device() {
    coverage := ctx.GetDirectDepProxyWithTag(getGcovProfileLibraryName(ctx), CoverageDepTag)
    deps.WholeStaticLibs = append(deps.WholeStaticLibs, android.OutputFileForModule(ctx, coverage, ""))
    flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv")
   }
  } else if clangCoverage {
   flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrFlag)
   if EnableContinuousCoverage(ctx) {
    flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm=-runtime-counter-relocation")
   }

   if ctx.Device() {
    coverage := ctx.GetDirectDepProxyWithTag(getClangProfileLibraryName(ctx), CoverageDepTag)
    deps.WholeStaticLibs = append(deps.WholeStaticLibs, android.OutputFileForModule(ctx, coverage, ""))
    flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,open")
   }
  }
 }

 return flags, deps
}

func (cov *coverage) begin(ctx BaseModuleContext, binary bool, test bool) {
 if IsCoverageEnabled(ctx, binary, test) {
  cov.Properties = SetCoverageProperties(ctx, cov.Properties, ctx.nativeCoverage(), ctx.useSdk(), ctx.sdkVersion())
 }
}

func IsCoverageEnabled(ctx android.BaseModuleContext, binary bool, test bool) bool {
 if ctx.Host() {
  // Only allow coverage for host modules if they are explicitly marked as tests
  // or if they are libraries (which might be dependencies of tests).
  // Build tools (binaries that are NOT tests) should be excluded.
  if binary && !test {
   return false
  }
  // Host coverage is only supported on Linux 64-bit binaries
  if !ctx.Os().Linux() {
   return false
  }
  if ctx.Arch().ArchType.Multilib == "lib32" {
   return false
  }
 }
 return true
}

func SetCoverageProperties(ctx android.BaseModuleContext, properties CoverageProperties, moduleTypeHasCoverage bool,
 useSdk bool, sdkVersion string) CoverageProperties {
 // Coverage is disabled globally
 if !ctx.DeviceConfig().NativeCoverageEnabled() {
  return properties
 }

 var needCoverageVariant bool
 var needCoverageBuild bool

 if moduleTypeHasCoverage {
  // Check if Native_coverage is set to false.  This property defaults to true.
  needCoverageVariant = BoolDefault(properties.Native_coverage, true)
  if useSdk && sdkVersion != "current" {
   // Native coverage is not supported for SDK versions < 23
   if fromApi, err := strconv.Atoi(sdkVersion); err == nil && fromApi < 23 {
    needCoverageVariant = false
   }
  }

  // Coverage is still untested with LFI
  if ctx.Target().LFI {
   needCoverageVariant = false
  }

  if needCoverageVariant {
   // Coverage variant is actually built with coverage if enabled for its module path
   needCoverageBuild = ctx.DeviceConfig().NativeCoverageEnabledForPath(ctx.ModuleDir())
  }
 }

 properties.NeedCoverageBuild = needCoverageBuild
 properties.NeedCoverageVariant = needCoverageVariant

 return properties
}

type IsNativeCoverageNeededContext interface {
 Config() android.Config
 DeviceConfig() android.DeviceConfig
 Device() bool
}

var _ IsNativeCoverageNeededContext = android.IncomingTransitionContext(nil)
var _ IsNativeCoverageNeededContext = android.BaseModuleContext(nil)
var _ IsNativeCoverageNeededContext = android.BottomUpMutatorContext(nil)

type UseCoverage interface {
 android.Module
 IsNativeCoverageNeeded(ctx IsNativeCoverageNeededContext) bool
}

// Coverage is an interface for non-CC modules to implement to be mutated for coverage
type Coverage interface {
 UseCoverage
 SetPreventInstall()
 HideFromMake()
 MarkAsCoverageVariant(bool)
 EnableCoverageIfNeeded()
}

type UseCoverageDeptag interface {
 IsNativeCoverageNeededDepTag(ctx IsNativeCoverageNeededContext) bool
}

type coverageTransitionMutator struct{}

func (c coverageTransitionMutator) split(ctx android.BaseModuleContext) []string {
 if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
  if c.coverage.Properties.NeedCoverageVariant {
   return []string{"", "cov"}
  }
 } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) {
  // APEX and Rust 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.
  return []string{"", "cov"}
 } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
  // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of
  // deps.
  return []string{"cov"}
 }

 return []string{""}
}

func (c coverageTransitionMutator) Split(ctx android.BaseModuleContext) []string {
 allSplits := c.split(ctx)
 if ctx.Config().GetBuildFlagBool("RELEASE_SOONG_COV_VARIANT_ON_DEMAND") {
  return allSplits[0:1]
 } else {
  return allSplits
 }
}

func (c coverageTransitionMutator) SplitOnDemand(ctx android.BaseModuleContext) []string {
 allSplits := c.split(ctx)
 if len(allSplits) <= 1 || !ctx.Config().GetBuildFlagBool("RELEASE_SOONG_COV_VARIANT_ON_DEMAND") {
  return nil
 } else {
  return allSplits[1:]
 }
}

func (c coverageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
 return sourceVariation
}

func (c coverageTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
 if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
  if !c.coverage.Properties.NeedCoverageVariant {
   return ""
  }
 } else if cov, ok := ctx.Module().(Coverage); ok {
  if !cov.IsNativeCoverageNeeded(ctx) {
   return ""
  }
 } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
  // Module only has a "cov" variation, so all incoming variations should use "cov".
  return "cov"
 } else {
  return ""
 }

 // non-coverage variants have PreventInstall = true, so we need certain deptags that are
 // used for installation to use the coverage variant so that filesystem modules will package
 // them correctly.
 if x, ok := ctx.DepTag().(UseCoverageDeptag); (ok && x.IsNativeCoverageNeededDepTag(ctx)) || ctx.DepTag() == android.RequiredDepTag {
  return "cov"
 }

 return incomingVariation
}

func (c coverageTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
 if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
  if variation == "" && c.coverage.Properties.NeedCoverageVariant {
   // Setup the non-coverage version and set HideFromMake and
   // PreventInstall to true.
   c.coverage.Properties.CoverageEnabled = false
   c.coverage.Properties.IsCoverageVariant = false
   c.Properties.HideFromMake = true
   c.Properties.PreventInstall = true
  } else if variation == "cov" {
   // The coverage-enabled version inherits HideFromMake,
   // PreventInstall from the original module.
   c.coverage.Properties.CoverageEnabled = c.coverage.Properties.NeedCoverageBuild
   c.coverage.Properties.IsCoverageVariant = true
  }
 } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) {
  // APEX and Rust 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.
  if variation == "" {
   cov.MarkAsCoverageVariant(false)
   cov.SetPreventInstall()
   cov.HideFromMake()
  } else if variation == "cov" {
   cov.MarkAsCoverageVariant(true)
   cov.EnableCoverageIfNeeded()
  }
 } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
  // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of
  // deps.
 }
}

func ParseSymbolFileForAPICoverage(ctx android.ModuleContext, symbolFile string) android.ModuleOutPath {
 apiLevelsJson := android.GetApiLevelsJson(ctx)
 symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
 outputFile := ctx.Module().(LinkableInterface).BaseModuleName() + ".xml"
 parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFile)
 rule := android.NewRuleBuilder(pctx, ctx).SandboxDisabled()
 rule.Command().
  BuiltTool("ndk_api_coverage_parser").
  Input(symbolFilePath).
  Output(parsedApiCoveragePath).
  Implicit(apiLevelsJson).
  FlagWithArg("--api-map ", apiLevelsJson.String())
 rule.Build("native_library_api_list", "Generate native API list based on symbol files for coverage measurement")
 return parsedApiCoveragePath
}

[Dauer der Verarbeitung: 0.22 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik