diff --git a/build_tools/github_actions/configure_asan_env.py b/build_tools/github_actions/configure_asan_env.py index bc024fed32d..765704e99f4 100644 --- a/build_tools/github_actions/configure_asan_env.py +++ b/build_tools/github_actions/configure_asan_env.py @@ -114,9 +114,28 @@ def _resolve_symbolizer(artifacts_dir: Path) -> tuple[Optional[Path], Optional[s return symbolizer.resolve(), None -def _resolve_library_path(artifacts_dir: Path) -> str: +def get_asan_runtime_path(artifacts_dir: Path) -> Path: + """Returns the configured runtime, or discovers it for standalone launchers.""" + configured = os.environ.get("ASAN_RUNTIME_PATH") + if configured: + runtime = Path(configured) + if not runtime.is_file(): + raise FileNotFoundError(f"ASAN_RUNTIME_PATH does not exist: {runtime}") + return runtime.resolve() + + runtime, warning = _resolve_asan_runtime(artifacts_dir) + if runtime is None: + raise FileNotFoundError(warning) + return runtime + + +def _resolve_library_path(artifacts_dir: Path, runtime: Path | None = None) -> str: lib_dir = (artifacts_dir / "lib").resolve() parts = [str(lib_dir), str(lib_dir / "rocm_sysdeps" / "lib")] + # -shared-libsan binaries and Python extensions need the clang resource + # directory as well as ROCm/lib, even when they do not preload ASan. + if runtime: + parts.append(str(runtime.parent)) existing = os.environ.get("LD_LIBRARY_PATH") if existing: parts.append(existing) @@ -140,7 +159,7 @@ def resolve_asan_env(artifacts_dir: Path) -> tuple[dict[str, str], list[str]]: if warning: warnings.append(warning) - env["LD_LIBRARY_PATH"] = _resolve_library_path(artifacts_dir) + env["LD_LIBRARY_PATH"] = _resolve_library_path(artifacts_dir, runtime) return env, warnings diff --git a/build_tools/github_actions/test_executable_scripts/test_hiptests.py b/build_tools/github_actions/test_executable_scripts/test_hiptests.py index 1f5d91faa53..6d3897b6b07 100644 --- a/build_tools/github_actions/test_executable_scripts/test_hiptests.py +++ b/build_tools/github_actions/test_executable_scripts/test_hiptests.py @@ -27,6 +27,7 @@ # Importing is_asan from amdgpu_family_matrix.py sys.path.append(str(THEROCK_DIR / "build_tools" / "github_actions")) from amdgpu_family_matrix import is_asan +from configure_asan_env import get_asan_runtime_path env = os.environ.copy() @@ -107,17 +108,7 @@ def get_asan_lib_path(): - arch = platform.machine() - CLANG_PATH = str(Path(THEROCK_BIN_DIR).parent / "lib" / "llvm" / "bin" / "clang++") - cmd = [f"{CLANG_PATH}", f"--print-file-name=libclang_rt.asan-{arch}.so"] - logging.info(f"++ Exec [{CLANG_PATH}]$ {shlex.join(cmd)}") - result = subprocess.run( - cmd, - check=True, - text=True, - capture_output=True, - ) - return result.stdout.strip() + return str(get_asan_runtime_path(THEROCK_BIN_DIR.resolve().parent)) def copy_dlls_exe_path(): diff --git a/build_tools/github_actions/test_executable_scripts/test_rocprofiler_sdk.py b/build_tools/github_actions/test_executable_scripts/test_rocprofiler_sdk.py index bb94de8d0ff..348acc74a0a 100644 --- a/build_tools/github_actions/test_executable_scripts/test_rocprofiler_sdk.py +++ b/build_tools/github_actions/test_executable_scripts/test_rocprofiler_sdk.py @@ -25,6 +25,7 @@ THEROCK_DIR = SCRIPT_DIR.parent.parent.parent sys.path.append(str(THEROCK_DIR / "build_tools" / "github_actions")) from amdgpu_family_matrix import is_asan +from configure_asan_env import get_asan_runtime_path # Base Paths THEROCK_BIN_DIR = os.getenv("THEROCK_BIN_DIR") @@ -97,29 +98,7 @@ def get_asan_runtime_library(): """Return the clang AddressSanitizer runtime path.""" - machine = platform.machine() - if machine in ("x86_64", "AMD64"): - arch = "x86_64" - elif machine == "aarch64": - arch = "aarch64" - else: - raise RuntimeError(f"Unsupported ASan runtime architecture: {machine}") - - asan_lib = f"libclang_rt.asan-{arch}.so" - result = subprocess.run( - [str(THEROCK_CLANG_PLUS_PATH), f"-print-file-name={asan_lib}"], - check=True, - capture_output=True, - text=True, - env=environ_vars, - ) - resolved = result.stdout.strip() - if not resolved or resolved == asan_lib or not Path(resolved).is_file(): - raise FileNotFoundError( - f"Could not locate ASan runtime '{asan_lib}' via {THEROCK_CLANG_PLUS_PATH} " - f"(got: '{resolved}')" - ) - return str(Path(resolved).resolve()) + return str(get_asan_runtime_path(THEROCK_PATH)) def setup_env(): @@ -134,7 +113,7 @@ def setup_env(): if is_asan(): # Installed test binaries are built with -shared-libsan, so the clang - # resource dir holding libclang_rt.asan-.so must be on the loader + # resource dir holding the ASan runtime must be on the loader # search path. Match rocprofiler-sdk sanitizer defaults for launchers. ld_lib_paths.append(str(Path(get_asan_runtime_library()).parent)) diff --git a/build_tools/github_actions/tests/configure_asan_env_test.py b/build_tools/github_actions/tests/configure_asan_env_test.py index 47493d7d994..796dcf429b6 100644 --- a/build_tools/github_actions/tests/configure_asan_env_test.py +++ b/build_tools/github_actions/tests/configure_asan_env_test.py @@ -56,6 +56,10 @@ def test_resolves_runtime_and_symbolizer(self): self.assertEqual(warnings, []) self.assertTrue(env["ASAN_RUNTIME_PATH"].endswith("asan.so")) self.assertTrue(env["ASAN_SYMBOLIZER_PATH"].endswith("llvm-symbolizer")) + self.assertIn( + str(Path(env["ASAN_RUNTIME_PATH"]).parent), + env["LD_LIBRARY_PATH"].split(":"), + ) def test_static_values_are_always_exported(self): with tempfile.TemporaryDirectory() as tmp: diff --git a/build_tools/github_actions/tests/rocprofiler_sdk_dashboard_test.py b/build_tools/github_actions/tests/rocprofiler_sdk_dashboard_test.py index 6aa6fe64786..aa101f0665a 100644 --- a/build_tools/github_actions/tests/rocprofiler_sdk_dashboard_test.py +++ b/build_tools/github_actions/tests/rocprofiler_sdk_dashboard_test.py @@ -88,13 +88,18 @@ def test_asan_dashboard_preserves_mainline_configuration_and_exclusions(self): patch.object(test_rocprofiler_sdk, "is_asan", return_value=True), patch.object( test_rocprofiler_sdk, - "get_asan_runtime_library", - return_value="/tmp/libclang_rt.asan-x86_64.so", + "get_asan_runtime_path", + return_value=Path("/tmp/libclang_rt.asan.so"), ), ): dashboard = self._generate() + command = test_rocprofiler_sdk.get_cmake_config_cmd() self.assertIn("-DROCPROFILER_MEMCHECK=AddressSanitizer", dashboard) + self.assertIn( + f"-DROCPROFILER_MEMCHECK_PRELOAD_ENV=LD_PRELOAD={Path('/tmp/libclang_rt.asan.so')}", + command, + ) self.assertIn( 'EXCLUDE "rocprofiler_sdk.unit.spm_core.check_packet_generation|', dashboard,