From 0df8153267f96da877febc5332240fa06ceb8533 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 23 Aug 2023 22:20:51 -0700 Subject: [PATCH] Fix adding manual ubsan runtime to static glibc binaries Sanitized glibc binaries get their runtime added by clang, not by Soong, but unsanitized glibc binaries with sanitized dependencies need their runtime added manually by Soong. Fix adding a static runtime dependency to static glibc binaries. Fixes: 297250415 Test: TestUbsan Change-Id: I4913326604f9efebd8ecd4aad2f109fad8b6a80c --- cc/sanitize.go | 12 ++++++------ cc/sanitize_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) 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) })