From 358056c058e43bfb2bbae8978fbfe4a8e4c84fb5 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Sat, 14 Apr 2018 01:03:35 -0700 Subject: [PATCH] Support coverage instrumentation for Linux host Bug: http://b/77792074 - Add the libclang_rt.profile runtime libraries directly to the compile command (for both host and target) instead of relying on the Clang driver. - Move the coverage mutator to PreDepsMutators so the mutation has already happened when runtime libraries are added during dependence computation. - Factor out cc/config/toolchain to identify libclang_rt.profile modules for the x86 and x86_64 host. Test: make NATIVE_COVERAGE=true produces coverage-enabled host binaries. Change-Id: I1ebc8cffdf11622bfc18199a57674672888b3a5f --- cc/cc.go | 14 +++++++------- cc/config/toolchain.go | 12 ++++++++++++ cc/config/x86_linux_bionic_host.go | 4 ++++ cc/config/x86_linux_host.go | 8 ++++++++ cc/coverage.go | 10 +++++++--- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index 9722cf088..1e313c0b7 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -40,6 +40,7 @@ func init() { ctx.BottomUp("ndk_api", ndkApiMutator).Parallel() ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel() ctx.BottomUp("begin", beginMutator).Parallel() + ctx.BottomUp("coverage", coverageLinkingMutator).Parallel() }) android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { @@ -54,7 +55,6 @@ func init() { ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator()) - ctx.BottomUp("coverage", coverageLinkingMutator).Parallel() ctx.TopDown("vndk_deps", sabiDepsMutator) ctx.TopDown("lto_deps", ltoDepsMutator) @@ -809,12 +809,15 @@ func (c *Module) deps(ctx DepsContext) Deps { if c.compiler != nil { deps = c.compiler.compilerDeps(ctx, deps) } - // Add the PGO dependency (the clang_rt.profile runtime library), which - // sometimes depends on symbols from libgcc, before libgcc gets added - // in linkerDeps(). + // clang_rt.profile runtime libraries necessary for PGO and coverage + // depend on symbols from libgcc. Add the runtime library dependency + // before libgcc gets added in linkerDeps(). if c.pgo != nil { deps = c.pgo.deps(ctx, deps) } + if c.coverage != nil { + deps = c.coverage.deps(ctx, deps) + } if c.linker != nil { deps = c.linker.linkerDeps(ctx, deps) } @@ -824,9 +827,6 @@ func (c *Module) deps(ctx DepsContext) Deps { if c.sanitize != nil { deps = c.sanitize.deps(ctx, deps) } - if c.coverage != nil { - deps = c.coverage.deps(ctx, deps) - } if c.sabi != nil { deps = c.sabi.deps(ctx, deps) } diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index ca863a7d7..19d282892 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -85,6 +85,8 @@ type Toolchain interface { AvailableLibraries() []string Bionic() bool + + profileRuntimeLibrary() string } type toolchainBase struct { @@ -169,6 +171,10 @@ func (toolchainBase) Bionic() bool { return true } +func (t toolchainBase) profileRuntimeLibrary() string { + return "" +} + func (t toolchainBase) ToolPath() string { return "" } @@ -240,6 +246,12 @@ func ThreadSanitizerRuntimeLibrary(t Toolchain) string { } func ProfileRuntimeLibrary(t Toolchain) string { + lib := t.profileRuntimeLibrary() + if lib != "" { + // Return the directly exported profile library + return lib + } + // Return the Android-specific library return SanitizerRuntimeLibrary(t, "profile") } diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go index a9fb1f661..290793e6f 100644 --- a/cc/config/x86_linux_bionic_host.go +++ b/cc/config/x86_linux_bionic_host.go @@ -151,6 +151,10 @@ func (t *toolchainLinuxBionic) Bionic() bool { return true } +func (t *toolchainLinuxBionic) profileRuntimeLibrary() string { + return "libclang_rt.profile-x86_64" +} + var toolchainLinuxBionicSingleton Toolchain = &toolchainLinuxBionic{} func linuxBionicToolchainFactory(arch android.Arch) Toolchain { diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index 354500eb0..653f819e0 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -270,6 +270,14 @@ func (t *toolchainLinuxX8664) YasmFlags() string { return "${config.LinuxX8664YasmFlags}" } +func (t *toolchainLinuxX86) profileRuntimeLibrary() string { + return "libclang_rt.profile-i386" +} + +func (t *toolchainLinuxX8664) profileRuntimeLibrary() string { + return "libclang_rt.profile-x86_64" +} + func (t *toolchainLinux) AvailableLibraries() []string { return linuxAvailableLibraries } diff --git a/cc/coverage.go b/cc/coverage.go index 391b11812..671353c9d 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -16,6 +16,7 @@ package cc import ( "android/soong/android" + "android/soong/cc/config" ) type CoverageProperties struct { @@ -38,6 +39,10 @@ func (cov *coverage) props() []interface{} { func (cov *coverage) begin(ctx BaseModuleContext) {} func (cov *coverage) deps(ctx BaseModuleContext, deps Deps) Deps { + if cov.Properties.CoverageEnabled { + runtimeLibrary := config.ProfileRuntimeLibrary(ctx.toolchain()) + deps.LateStaticLibs = append(deps.LateStaticLibs, runtimeLibrary) + } return deps } @@ -99,9 +104,8 @@ func coverageLinkingMutator(mctx android.BottomUpMutatorContext) { if !mctx.DeviceConfig().NativeCoverageEnabled() { // Coverage is disabled globally - } else if mctx.Host() { - // TODO(dwillemsen): because of -nodefaultlibs, we must depend on libclang_rt.profile-*.a - // Just turn off for now. + } else if mctx.Darwin() || mctx.Windows() { + // Coverage not supported for Darwin and Windows } else if c.coverage.Properties.Native_coverage != nil { enabled = *c.coverage.Properties.Native_coverage } else {