build-logic: link sanitizer runtime for the fuzzer shared lib#646
Conversation
commonLinuxLinkerArgs() carries -Wl,-z,defs, which forbids undefined symbols in the output. The fuzzer objects are instrumented with -fsanitize=address,undefined and therefore reference __asan_*/__ubsan_*, but -fsanitize=address only links the sanitizer runtime into *executables*, not shared libraries. So the fuzzer .so ends up with undefined __asan_*/__ubsan_* and the link fails under -z defs on any box where the fuzzer config is active (clang with libFuzzer, non-musl). The asan config already solves this by linking the matching runtime explicitly via locateLibasan (-lclang_rt.asan-<arch> on clang, which also provides UBSan symbols; -lasan + -lubsan on gcc). Apply the same, already-proven treatment to configureFuzzer: thread the detected compiler through and add the runtime to the Linux linker args. CI never hit this because its publish/build path passes --exclude-task compileFuzzer and only assembles the release jar, so the fuzzer is never linked there. It only bites a local build that links all active configs (e.g. publishToMavenLocal on a clang box). The macOS branch is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1d186990d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| listOf("-L$asanLibDir", "-l$asanLibName", | ||
| "-Wl,-rpath,$asanLibDir") + | ||
| ubsanLibs + | ||
| fuzzerLinkerArgs |
There was a problem hiding this comment.
Preload ASan for fuzzer test JVMs
When the Linux fuzzer config is used by the generated Java tasks (for example testFuzzer from ProfilerTestPlugin), these new link args add a DT_NEEDED dependency on the ASan runtime but the fuzzer testEnvironment still never sets LD_PRELOAD. An unsanitized JVM that later loads this ASan-instrumented libjavaProfiler.so aborts before tests start with the usual “ASan runtime does not come first” error; configureAsan avoids that by preloading the same libasan. Please mirror that here when libasan != null.
Useful? React with 👍 / 👎.
CI Test ResultsRun: #29029761735 | Commit:
Status Overview
Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled Failed Testsglibc-amd64/debug / 8-ibmJob: View logs No detailed failure information available. Check the job logs. Summary: Total: 32 | Passed: 31 | Failed: 1 Updated: 2026-07-09 15:48:35 UTC |
|
Re: the Codex review comment on the fuzzer test environment — confirmed and reproduced locally, and it's a real (but separate) issue. The link fix here does let the auto-generated
So making Important: Keeping this PR scoped to the link fix and tracking the |
What
configureFuzzernow links the sanitizer runtime into the fuzzer shared library on Linux, mirroring the existingconfigureAsantreatment. The detected compiler is threaded through so the right runtime is chosen (clang:-lclang_rt.asan-<arch>, which also supplies UBSan symbols; gcc:-lasan+-lubsan).Why
commonLinuxLinkerArgs()includes-Wl,-z,defs, which forbids undefined symbols in the output. The fuzzer objects are compiled with-fsanitize=address,undefined, so they reference__asan_*/__ubsan_*— but-fsanitize=addressonly links the sanitizer runtime into executables, not shared libraries. The fuzzer.sois therefore left with undefined__asan_*/__ubsan_*and the link fails under-z defs:The
asanconfig already solves exactly this vialocateLibasan; this change applies the same, already-proven pattern to the fuzzer config.Why CI didn't catch it
The publish/build path passes
--exclude-task compileFuzzer(.gitlab/scripts/deploy.sh) and the build job only assembles:ddprof-lib:assembleReleaseJar, so the fuzzer is never linked in CI. The bug only surfaces on a local build that links all active configs — e.g.publishToMavenLocalon a clang box wherehasFuzzer()is true (non-musl, clang with libFuzzer).Scope / risk
fuzzerLinkerArgs).--exclude-task compileFuzzeris left in place (it still saves build time); this change just makes the fuzzer link work when it is built.Testing
./gradlew ddprof-lib:linkFuzzersucceeds on a clang Linux box (Successfully linked libjavaProfiler.so). Before this change it failed at link with the undefined__asan_*/__ubsan_*references above.🤖 Generated with Claude Code