Skip to content

[Feature]: Publish standalone MSAN libc++ runtime archives for CPU testingΒ #9856

Open

Description

@benvanik

HRX/Loom needs a downloadable, versioned MSAN C++ runtime package so its CPU tests, including GoogleTest and C++ production code, can run under MemorySanitizer. TheRock already produces the compiler that could build this package; the additional compilation is limited to libc++ and libc++abi.

The artifact is on the order of 4–8 MB compressed, with roughly 1,700 files, almost all headers. A comparable LLVM 22.1.8 runtime archive has the following measured footprint:

Measure Observed value
Regular files 1,695: 1,686 headers and 9 library/support files
Symlinks 5
Unpacked file contents 32.1 MB
Published zstd archive 3.92 MB
Same tar payload recompressed with gzip level 6 7.73 MB

That reference includes static/shared libc++, libc++abi, and an additional unwinder. It establishes the size class; TheRock's exact revision and debug settings will determine its final size.

For build-work scale, LLVM's MSAN-with-origins runtime step configured, built, and installed libc++/libc++abi in 15 seconds, with 155 compilation actions. This was upstream CI on 96 logical CPUs with ccache enabled; it is not a cold-build estimate for TheRock. Archive creation and the package smoke checks below add work beyond that measured step. Runtime-only cold time should be measured when integrating the package. LLVM's full check-runtimes suite is separate from producing the archive and is not a requested addition to this publication flow.

Our instrumented GoogleTest binaries currently link against ordinary system libstdc++. A representative failure occurs before the tests run, through testing::internal::StringStreamToString and std::stringstream::str(). Instrumenting GoogleTest itself does not supply shadow tracking inside the standard library. A distributable instrumented runtime would make this a pinned build dependency for downstream projects.

The requested deliverable is a standalone archive at an immutable, versioned public HTTPS URL, checked against a published SHA-256, and extracted into an arbitrary directory. Our immediate consumer is Linux x86-64 CPU CI. The package would identify its compatible compiler release and host platform, and be fetchable independently of GPU libraries and the full ROCm SDK.

The filename should identify MSAN, the host architecture, and the compiler build it accompanies. Publish one archive per host/compiler build through an existing release channel and its public download index, with documented publication cadence and retention for downstream version pins. This CPU runtime is shared across GPU families.

Package contents

Preserve the normal install-cxx and install-cxxabi output:

Contents Purpose
libc++ headers under include/c++/v1, including generated __config_site and any additional target-specific include directory Compile consumers against the configuration used to build the libraries
libc++abi headers, including cxxabi.h and __cxxabi_config.h Matching C++ ABI interfaces
Instrumented libc++.a, libc++abi.a, and corresponding shared libraries Support static and shared C++ runtime selection
Installed symlinks, linker scripts, and support archives Preserve the upstream install layout and link behavior
Licenses and build identification Record LLVM revision, producer/compiler release, host triple, platform baseline, and sanitizer settings

Use a distinct runtime prefix so the instrumented libraries can coexist with the ordinary SDK, including when assembled into its install tree. Runtime selection remains explicit in the consuming MSAN configuration. The paired compiler package must supply compiler-rt's MSAN and MSAN C++ support libraries, sanitizer interface headers, and a symbolizer. Their presence in the published compiler package is part of the acceptance check.

Consumer documentation should give fetch/checksum/extract and compile/link/run examples for the published layout, including origin tracking, symbolization, and shared-library lookup. State the minimum Linux/glibc baseline and external runtime dependencies, including the system unwinder. Extraction and explicit downstream compiler/linker settings should suffice to use the package.

Existing upstream recipe

LLVM's sanitizer buildbot already builds these libraries separately in build_stage2. The relevant configuration uses the existing Clang as CMAKE_C_COMPILER and CMAKE_CXX_COMPILER, with the source rooted at llvm-project/runtimes:

-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"
-DLLVM_USE_SANITIZER=MemoryWithOrigins
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF
-DLLVM_ENABLE_PIC=ON
-DCMAKE_BUILD_TYPE=Release

The runtime configure/build/install step ends before that script proceeds to build LLVM itself as a sanitizer test subject. Only the runtime step is needed here. LLVM also documents this standalone build in its libc++ vendor guide. The recipe uses the system unwinder and preserves origin tracking without adding an MSAN ignorelist.

Proposed fit in TheRock

The following uses existing build interfaces; the exact artifact name and release location can follow TheRock's conventions:

  1. Add a runtime subproject under compiler/ using the same LLVM source revision, a separate binary/install directory, and COMPILER_TOOLCHAIN amd-llvm. This reuses the existing compiler dependency. The subproject is host-only and can use DISABLE_AMDGPU_TARGETS.
  2. Register a target-neutral artifact in the compiler group of BUILD_TOPOLOGY.toml, with its own artifact descriptor, as an optional side artifact of the ordinary compiler build. Sanitizer flags apply only to this runtime build; the ordinary compiler and other ROCm projects retain their existing configurations. Ensure _FORTIFY_SOURCE is disabled for the MSAN runtime, including when TheRock's hardening policy is enabled. The existing THEROCK_DISABLE_FORTIFY mechanism provides a targeted integration point.
  3. Produce one flattened runtime archive from its required artifact components and publish it alongside the matching compiler release. TheRock's artifact format retains build-tree paths, while its archive packaging already describes flattening into an install tree. A versioned .tar.gz would fit the current release tarball format.

The public archive and checksum must be promoted together. Intermediate artifact archives already have hash sidecars; the current publish_tarballs copies *.tar.gz, so publishing the final archive's checksum needs explicit coverage. The checksum must describe the final flattened archive's bytes.

Package acceptance

These checks belong to package validation and exercise the final downloadable archive using its documented consumer steps:

  • Find the versioned archive and checksum in the public download index and fetch them without authentication; verify the digest, extract to a new prefix, and build/run consumers without access to the producer's build or source directories.
  • Exercise both advertised static and shared runtime forms, verifying that headers and libraries resolve to the extracted package.
  • Run a small C++ smoke against the extracted package, including a standard library operation and exception handling. A deliberate uninitialized-read control must fail with an MSAN diagnostic and origin information.
  • Verify that the instrumented package coexists with the normal SDK and that a runtime-only rebuild reuses the already-built compiler.

These are CPU package smokes. HRX/Loom owns downstream qualification with its actual GoogleTest targets, C++ frontend, and broader CPU suite. The incremental producer work is the C++ runtime build, packaging, and those focused smokes; build time and archive size should be measured during implementation.

Related TheRock work: ASAN tarball publication and multi-arch tarball delivery cover analogous release integration. The missing ASAN indexes and ASAN install-prefix collision are the reasons to make discoverability and coexistence explicit here.


AI assistance: The research and text above were prepared with Codex assistance. The request and scope were reviewed, and publication approved, by the submitter.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions