diff --git a/cc/sanitize.go b/cc/sanitize.go index 30bce9bff..8eea7db7b 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1650,12 +1650,12 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { Bool(sanProps.Fuzzer) || Bool(sanProps.Undefined) || Bool(sanProps.All_undefined) { - if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) { - // Use a static runtime for static binaries. - // Also use a static runtime for musl to match - // what clang does for glibc. Otherwise dlopening - // libraries that depend on libclang_rt.ubsan_standalone.so - // fails with: + if toolchain.Musl() || c.staticBinary() { + // Use a static runtime for static binaries. For sanitized glibc binaries the runtime is + // added automatically by clang, but for static glibc binaries that are not sanitized but + // have a sanitized dependency the runtime needs to be added manually. + // Also manually add a static runtime for musl to match what clang does for glibc. + // Otherwise dlopening libraries that depend on libclang_rt.ubsan_standalone.so fails with: // Error relocating ...: initial-exec TLS resolves to dynamic definition addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)+".static", true) } else { diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go index 29b17d415..49117a082 100644 --- a/cc/sanitize_test.go +++ b/cc/sanitize_test.go @@ -714,6 +714,15 @@ func TestUbsan(t *testing.T) { ], } + cc_binary { + name: "static_bin_with_ubsan_dep", + static_executable: true, + host_supported: true, + static_libs: [ + "libubsan_diag", + ], + } + cc_library_shared { name: "libshared", host_supported: true, @@ -741,6 +750,17 @@ func TestUbsan(t *testing.T) { } } + cc_library_static { + name: "libubsan_diag", + host_supported: true, + sanitize: { + undefined: true, + diag: { + undefined: true, + }, + }, + } + cc_library_static { name: "libstatic", host_supported: true, @@ -763,6 +783,7 @@ func TestUbsan(t *testing.T) { sharedVariant := variant + "_shared" minimalRuntime := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant) + standaloneRuntime := result.ModuleForTests("libclang_rt.ubsan_standalone.static", staticVariant) // The binaries, one with ubsan and one without binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant) @@ -770,6 +791,7 @@ func TestUbsan(t *testing.T) { libSharedUbsan := result.ModuleForTests("libsharedubsan", sharedVariant) binDependsUbsanShared := result.ModuleForTests("bin_depends_ubsan_shared", variant) binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant) + staticBin := result.ModuleForTests("static_bin_with_ubsan_dep", variant) android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs", strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "), @@ -810,6 +832,11 @@ func TestUbsan(t *testing.T) { android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_no_ubsan static libs", strings.Split(binNoUbsan.Rule("ld").Args["ldFlags"], " "), "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base()) + + android.AssertStringListContains(t, "missing libclang_rt.ubsan_standalone.static in static_bin_with_ubsan_dep static libs", + strings.Split(staticBin.Rule("ld").Args["libFlags"], " "), + standaloneRuntime.OutputFiles(t, "")[0].String()) + } t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })