mirror of
https://github.com/servo/servo.git
synced 2025-08-02 04:00:32 +01:00
Extend --with-asan to support C/C++ code (#36873)
`--with-asan` now also will instrument C/C++ code. This also increases the requirements on the user environment, since a clang compiler with the same major version as the LLVM version rustc is using must be in PATH. ASAN without C/C++ code is IMHO not so interesting, so I'm not sure if it would be worth adding a separate flag. Testing: Manual testing with `--with-asan`. I believe we don't run ASAN in CI yet, although perhaps we should. Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
e702bde9bf
commit
d2afe00f7b
2 changed files with 55 additions and 9 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -4645,7 +4645,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mozjs"
|
name = "mozjs"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
source = "git+https://github.com/servo/mozjs#d1525dfaee22cc1ea9ee16c552cdeedaa9f20741"
|
source = "git+https://github.com/servo/mozjs#728acdf3d4ce0604e9f75dd1d539dc6f291ccec7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.71.1",
|
"bindgen 0.71.1",
|
||||||
"cc",
|
"cc",
|
||||||
|
@ -4656,8 +4656,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mozjs_sys"
|
name = "mozjs_sys"
|
||||||
version = "0.128.9-1"
|
version = "0.128.9-2"
|
||||||
source = "git+https://github.com/servo/mozjs#d1525dfaee22cc1ea9ee16c552cdeedaa9f20741"
|
source = "git+https://github.com/servo/mozjs#728acdf3d4ce0604e9f75dd1d539dc6f291ccec7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.71.1",
|
"bindgen 0.71.1",
|
||||||
"cc",
|
"cc",
|
||||||
|
|
|
@ -13,10 +13,11 @@ import os.path as path
|
||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
|
|
||||||
import notifypy
|
import notifypy
|
||||||
|
|
||||||
|
@ -40,6 +41,32 @@ SUPPORTED_ASAN_TARGETS = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu",
|
||||||
"x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]
|
"x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_rustc_llvm_version() -> Optional[List[int]]:
|
||||||
|
"""Determine the LLVM version of `rustc` and return it as a List[major, minor, patch, ...]
|
||||||
|
|
||||||
|
In some cases we want to ensure that the LLVM version of rustc and clang match, e.g.
|
||||||
|
when using ASAN for both C/C++ and Rust code, we want to use the same ASAN implementation.
|
||||||
|
This function assumes that rustc points to the rust compiler we are interested in, which should
|
||||||
|
be valid in both rustup managed environment and on nix.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['rustc', '--version', '--verbose'], encoding='utf-8', capture_output=True)
|
||||||
|
result.check_returncode()
|
||||||
|
for line in result.stdout.splitlines():
|
||||||
|
line_lowercase = line.lower()
|
||||||
|
if line_lowercase.startswith("llvm version:"):
|
||||||
|
llvm_version = line_lowercase.strip("llvm version:")
|
||||||
|
llvm_version = llvm_version.strip()
|
||||||
|
version = llvm_version.split('.')
|
||||||
|
print(f"Info: rustc is using LLVM version {'.'.join(version)}")
|
||||||
|
return version
|
||||||
|
else:
|
||||||
|
print(f"Error: Couldn't find LLVM version in output of `rustc --version --verbose`: `{result.stdout}`")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: Failed to determine rustc version: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@CommandProvider
|
@CommandProvider
|
||||||
class MachCommands(CommandBase):
|
class MachCommands(CommandBase):
|
||||||
@Command('build', description='Build Servo', category='build')
|
@Command('build', description='Build Servo', category='build')
|
||||||
|
@ -99,11 +126,30 @@ class MachCommands(CommandBase):
|
||||||
env["RUSTFLAGS"] = env.get("RUSTFLAGS", "") + " -Zsanitizer=address"
|
env["RUSTFLAGS"] = env.get("RUSTFLAGS", "") + " -Zsanitizer=address"
|
||||||
opts += ["-Zbuild-std"]
|
opts += ["-Zbuild-std"]
|
||||||
kwargs["target_override"] = target_triple
|
kwargs["target_override"] = target_triple
|
||||||
# TODO: Investigate sanitizers in C/C++ code:
|
|
||||||
# env.setdefault("CFLAGS", "")
|
# Note: We want to use the same clang/LLVM version as rustc.
|
||||||
# env.setdefault("CXXFLAGS", "")
|
rustc_llvm_version = get_rustc_llvm_version()
|
||||||
# env["CFLAGS"] += " -fsanitize=address"
|
if rustc_llvm_version is None:
|
||||||
# env["CXXFLAGS"] += " -fsanitize=address"
|
raise RuntimeError("Unable to determine necessary clang version for ASAN support")
|
||||||
|
llvm_major: int = rustc_llvm_version[0]
|
||||||
|
target_clang = f"clang-{llvm_major}"
|
||||||
|
target_cxx = f"clang++-{llvm_major}"
|
||||||
|
if shutil.which(target_clang) is None or shutil.which(target_cxx) is None:
|
||||||
|
raise RuntimeError(f"--with-asan requires `{target_clang}` and `{target_cxx}` to be in PATH")
|
||||||
|
env.setdefault("TARGET_CC", target_clang)
|
||||||
|
env.setdefault("TARGET_CXX", target_cxx)
|
||||||
|
# TODO: We should also parse the LLVM version from the clang compiler we chose.
|
||||||
|
# It's unclear if the major version being the same is sufficient.
|
||||||
|
|
||||||
|
# We need to use `TARGET_CFLAGS`, since we don't want to compile host dependencies with ASAN,
|
||||||
|
# since that causes issues when building build-scripts / proc macros.
|
||||||
|
env.setdefault("TARGET_CFLAGS", "")
|
||||||
|
env.setdefault("TARGET_CXXFLAGS", "")
|
||||||
|
env["TARGET_CFLAGS"] += " -fsanitize=address"
|
||||||
|
env["TARGET_CXXFLAGS"] += " -fsanitize=address"
|
||||||
|
env["TARGET_LDFLAGS"] = "-static-libasan"
|
||||||
|
# By default build mozjs from source to enable ASAN with mozjs.
|
||||||
|
env.setdefault("MOZJS_FROM_SOURCE", "1")
|
||||||
|
|
||||||
# asan replaces system allocator with asan allocator
|
# asan replaces system allocator with asan allocator
|
||||||
# we need to make sure that we do not replace it with jemalloc
|
# we need to make sure that we do not replace it with jemalloc
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue