#!/usr/bin/env python3 """Build and exercise the patched native library in a fresh evidence directory.""" import argparse import json import os import pathlib import platform import shlex import subprocess parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--output", type=pathlib.Path, required=True) parser.add_argument("--sanitizer", choices=["none", "address", "thread"], default="none") parser.add_argument("--full", action="store_true", help="Also allocate the 2080 MiB full dataset") args = parser.parse_args() root = pathlib.Path(__file__).resolve().parents[1] out = args.output.resolve() out.mkdir(parents=True, exist_ok=False) commands = [] def run(label, command): print(label, flush=True) with (out / (label + ".log")).open("x") as log: result = subprocess.run([str(c) for c in command], cwd=root, stdout=log, stderr=subprocess.STDOUT) commands.append({"label": label, "argv": [str(c) for c in command], "returncode": result.returncode}) (out / "commands.json").write_text(json.dumps(commands, indent=2) + "\n") if result.returncode: raise SystemExit(f"{label} failed with {result.returncode}; see {out / (label + '.log')}") flags = [] if args.sanitizer == "address": flags = ["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] elif args.sanitizer == "thread": flags = ["-fsanitize=thread", "-fno-omit-frame-pointer"] cmake = ["cmake", "-S", root / "vendor/randomx", "-B", out / "build", "-DCMAKE_BUILD_TYPE=RelWithDebInfo", "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", "-DCMAKE_C_FLAGS=" + " ".join(flags), "-DCMAKE_CXX_FLAGS=" + " ".join(flags)] if platform.system() == "Darwin": version = platform.mac_ver()[0] cmake.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=" + version) flags.append("-mmacosx-version-min=" + version) run("configure", cmake) run("build", ["cmake", "--build", out / "build", "--target", "randomx", "-j", "2"]) source = "check-randomx-vm-race.cpp" if args.sanitizer == "thread" else "check-native-hardening.cpp" link = [*shlex.split(os.environ.get("CXX", "c++")), "-std=c++11", "-O2", "-g", *flags, "-I", root / "vendor/randomx/src", root / "reviews" / source, out / "build/librandomx.a", "-pthread", "-o", out / "check"] if platform.system() == "Linux" and args.sanitizer != "thread": link.append("-Wl,--wrap=allocMemoryPages,--wrap=freePagedMemory,--wrap=free,--wrap=mprotect,-z,noexecstack") run("link", link) run("race" if args.sanitizer == "thread" else "light", [out / "check"]) if args.full and args.sanitizer != "thread": run("full", [out / "check", "full"]) print(f"Passed; evidence: {out}")