mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
WIP: TSAN
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
fc217b85ce
commit
1f3e3af432
4 changed files with 73 additions and 26 deletions
|
@ -93,7 +93,7 @@ class MachCommands(CommandBase):
|
|||
no_package=False,
|
||||
verbose=False,
|
||||
very_verbose=False,
|
||||
sanitizer: Optional[SanitizerKind] = None,
|
||||
sanitizer: SanitizerKind = SanitizerKind.NONE,
|
||||
flavor=None,
|
||||
**kwargs,
|
||||
):
|
||||
|
@ -113,6 +113,7 @@ class MachCommands(CommandBase):
|
|||
if very_verbose:
|
||||
opts += ["-vv"]
|
||||
self.config["build"]["sanitizer"] = sanitizer
|
||||
assert sanitizer.is_tsan()
|
||||
|
||||
env = self.build_env()
|
||||
self.ensure_bootstrapped()
|
||||
|
@ -234,18 +235,25 @@ class MachCommands(CommandBase):
|
|||
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:
|
||||
env.setdefault("TARGET_CC", target_clang)
|
||||
env.setdefault("TARGET_CXX", target_cxx)
|
||||
env.setdefault("TARGET_CC", 'clang')
|
||||
env.setdefault("TARGET_CXX", 'clang++')
|
||||
else:
|
||||
# libasan can be compatible across multiple compiler versions and has a
|
||||
# runtime check, which would fail if we used incompatible compilers, so
|
||||
# we can try and fallback to the default clang.
|
||||
env.setdefault("TARGET_CC", "clang")
|
||||
env.setdefault("TARGET_CXX", "clang++")
|
||||
env.setdefault("TARGET_CC", target_clang)
|
||||
env.setdefault("TARGET_CXX", target_cxx)
|
||||
# By default, build mozjs from source to enable Sanitizers in mozjs.
|
||||
env.setdefault("MOZJS_FROM_SOURCE", "1")
|
||||
|
||||
if sanitizer == sanitizer.ASAN:
|
||||
# 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.
|
||||
# The actual flags will be appended below depending on the sanitizer kind.
|
||||
env.setdefault("TARGET_CFLAGS", "")
|
||||
env.setdefault("TARGET_CXXFLAGS", "")
|
||||
env.setdefault("RUSTFLAGS", "")
|
||||
|
||||
if sanitizer is sanitizer.ASAN:
|
||||
if target_triple not in SUPPORTED_ASAN_TARGETS:
|
||||
print(
|
||||
"AddressSanitizer is currently not supported on this platform\n",
|
||||
|
@ -254,18 +262,18 @@ class MachCommands(CommandBase):
|
|||
sys.exit(1)
|
||||
|
||||
# Enable asan
|
||||
env["RUSTFLAGS"] = env.get("RUSTFLAGS", "") + " -Zsanitizer=address"
|
||||
|
||||
# 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["RUSTFLAGS"] += " -Zsanitizer=address"
|
||||
env["TARGET_CFLAGS"] += " -fsanitize=address"
|
||||
env["TARGET_CXXFLAGS"] += " -fsanitize=address"
|
||||
|
||||
# asan replaces system allocator with asan allocator
|
||||
# we need to make sure that we do not replace it with jemalloc
|
||||
self.features.append("servo_allocator/use-system-allocator")
|
||||
elif sanitizer is SanitizerKind.TSAN:
|
||||
env["RUSTFLAGS"] += " -Zsanitizer=thread"
|
||||
env["TARGET_CFLAGS"] += " -fsanitize=thread"
|
||||
env["TARGET_CXXFLAGS"] += " -fsanitize=thread"
|
||||
|
||||
return None
|
||||
|
||||
def notify(self, title: str, message: str):
|
||||
|
|
|
@ -307,7 +307,7 @@ class CommandBase(object):
|
|||
self.config["build"].setdefault("incremental", None)
|
||||
self.config["build"].setdefault("webgl-backtrace", False)
|
||||
self.config["build"].setdefault("dom-backtrace", False)
|
||||
self.config["build"].setdefault("sanitizer", None)
|
||||
self.config["build"].setdefault("sanitizer", SanitizerKind.NONE)
|
||||
|
||||
self.config.setdefault("android", {})
|
||||
self.config["android"].setdefault("sdk", "")
|
||||
|
@ -548,6 +548,14 @@ class CommandBase(object):
|
|||
const=SanitizerKind.ASAN,
|
||||
help="Build with AddressSanitizer",
|
||||
),
|
||||
CommandArgument(
|
||||
"--with-tsan",
|
||||
group="Sanitizer",
|
||||
dest="sanitizer",
|
||||
action="store_const",
|
||||
const=SanitizerKind.TSAN,
|
||||
help="Build with ThreadSanitizer",
|
||||
),
|
||||
]
|
||||
|
||||
if build_configuration:
|
||||
|
|
|
@ -186,8 +186,10 @@ class PackageCommands(CommandBase):
|
|||
"-p",
|
||||
f"buildMode={build_mode}",
|
||||
]
|
||||
if sanitizer == SanitizerKind.ASAN:
|
||||
if sanitizer.is_asan():
|
||||
hvigor_command.extend(["-p", "ohos-debug-asan=true"])
|
||||
elif sanitizer.is_tsan():
|
||||
hvigor_command.extend(["-p", "ohos-enable-tsan=true"])
|
||||
|
||||
# Detect if PATH already has hvigor, or else fallback to npm installation
|
||||
# provided via HVIGOR_PATH
|
||||
|
|
|
@ -26,8 +26,21 @@ import servo.util as util
|
|||
|
||||
|
||||
class SanitizerKind(Enum):
|
||||
UNKNOWN = 0
|
||||
NONE = 0
|
||||
ASAN = 1
|
||||
TSAN = 2
|
||||
|
||||
# Apparently enums don't always compare across modules, so we define
|
||||
# helper methods.
|
||||
def is_asan(self) -> bool:
|
||||
return self is self.ASAN
|
||||
|
||||
def is_tsan(self) -> bool:
|
||||
return self is self.TSAN
|
||||
|
||||
# Returns true if a sanitizer is enabled.
|
||||
def is_some(self) -> bool:
|
||||
return self is not self.NONE
|
||||
|
||||
|
||||
class BuildTarget(object):
|
||||
|
@ -403,8 +416,9 @@ class OpenHarmonyTarget(CrossBuildTarget):
|
|||
bindgen_extra_clangs_args = bindgen_extra_clangs_args + " " + ohos_cflags_str
|
||||
env[bindgen_extra_clangs_args_var] = bindgen_extra_clangs_args
|
||||
|
||||
# On OpenHarmony we add some additional flags when asan is enabled
|
||||
if config["build"]["sanitizer"] == SanitizerKind.ASAN:
|
||||
sanitizer: SanitizerKind = config["build"]["sanitizer"]
|
||||
san_compile_flags = []
|
||||
if sanitizer.is_some():
|
||||
# Lookup `<sdk>/native/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.asan.so`
|
||||
lib_clang = llvm_toolchain.joinpath("lib", "clang")
|
||||
children = [f.path for f in os.scandir(lib_clang) if f.is_dir()]
|
||||
|
@ -412,6 +426,12 @@ class OpenHarmonyTarget(CrossBuildTarget):
|
|||
raise RuntimeError(f"Expected exactly 1 libclang version: `{children}`")
|
||||
lib_clang_version_dir = pathlib.Path(children[0])
|
||||
libclang_arch = lib_clang_version_dir.joinpath("lib", clang_target_triple).resolve()
|
||||
# Use the clangrt from the NDK to use the same library for both C++ and Rust.
|
||||
env["RUSTFLAGS"] += " -Zexternal-clangrt"
|
||||
san_compile_flags.append("-fno-omit-frame-pointer")
|
||||
|
||||
# On OpenHarmony we add some additional flags when asan is enabled
|
||||
if sanitizer.is_asan():
|
||||
libasan_so_path = libclang_arch.joinpath("libclang_rt.asan.so")
|
||||
libasan_preinit_path = libclang_arch.joinpath("libclang_rt.asan-preinit.a")
|
||||
if not libasan_so_path.exists():
|
||||
|
@ -428,23 +448,32 @@ class OpenHarmonyTarget(CrossBuildTarget):
|
|||
]
|
||||
)
|
||||
|
||||
# Use the clangrt from the NDK to use the same library for both C++ and Rust.
|
||||
env["RUSTFLAGS"] += " -Zexternal-clangrt"
|
||||
|
||||
asan_compile_flags = (
|
||||
" -fsanitize=address -shared-libasan -fno-omit-frame-pointer -fsanitize-recover=address"
|
||||
)
|
||||
san_compile_flags.extend([ "-fsanitize=address", "-shared-libasan", "-fsanitize-recover=address"])
|
||||
|
||||
arch_asan_ignore_list = lib_clang_version_dir.joinpath("share", "asan_ignorelist.txt")
|
||||
if arch_asan_ignore_list.exists():
|
||||
asan_compile_flags += " -fsanitize-system-ignorelist=" + str(arch_asan_ignore_list)
|
||||
san_compile_flags.append("-fsanitize-system-ignorelist=" + str(arch_asan_ignore_list))
|
||||
else:
|
||||
print(f"Warning: Couldn't find system ASAN ignorelist at `{arch_asan_ignore_list}`")
|
||||
env["TARGET_CFLAGS"] += asan_compile_flags
|
||||
env["TARGET_CXXFLAGS"] += asan_compile_flags
|
||||
elif sanitizer.is_tsan():
|
||||
libtsan_so_path = libclang_arch.joinpath("libclang_rt.tsan.so")
|
||||
builtins_path = libclang_arch.joinpath("libclang_rt.builtins.a")
|
||||
|
||||
link_args.extend(
|
||||
[
|
||||
"-fsanitize=thread",
|
||||
"--rtlib=compiler-rt",
|
||||
"-shared-libsan",
|
||||
str(libtsan_so_path),
|
||||
str(builtins_path)
|
||||
]
|
||||
)
|
||||
san_compile_flags.append("-shared-libsan")
|
||||
|
||||
link_args = [f"-Clink-arg={arg}" for arg in link_args]
|
||||
env["RUSTFLAGS"] += " " + " ".join(link_args)
|
||||
env["TARGET_CFLAGS"] += " " + " ".join(san_compile_flags)
|
||||
env["TARGET_CXXFLAGS"] += " " + " ".join(san_compile_flags)
|
||||
|
||||
def binary_name(self) -> str:
|
||||
return "libservoshell.so"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue