From b044efaa5123cc1498def6566b785a76184dfd99 Mon Sep 17 00:00:00 2001 From: Santeri Hannula Date: Wed, 9 Oct 2024 15:39:14 +0300 Subject: [PATCH] build: add build opts for enabling sanitizers --- INSTALL.md | 22 +++++++++++++ build.zig | 81 ++++++++++++++++++++++++++++++++++++++++++++++- pkg/c3/portable.h | 6 +++- 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 4e9ef81007..229154dc2e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -28,6 +28,22 @@ pro hand -p true -s false -n false SIGBUS pro hand -p true -s false -n false SIGSEGV ``` +### Sanitizers + +Musl does not have proper sanitizer support, so until we support native (GNU) linux builds, these are limited to mac only. + +In order to use address sanitizer (`-Dasan`) and undefined behavior sanitizer (`-Dubsan`), you need to have version 18 of llvm installed on your machine. You also have to build natively, since cross-compilation is not supported. + +macOS: +```terminal +brew install llvm@18 +``` + + + + + + ## Build Once you install `zig`, you're ready to build: @@ -73,6 +89,12 @@ Supported values: Provide additional compiler flags. These propagate to all build artifacts and dependencies. +#### `-Dasan` +Enable address sanitizer. Only supported in native macos builds. Requires llvm 18, see [prerequisites](#sanitizers). + +#### `-Dubsan` +Enable undefined behavior sanitizer. Only supported in native macos builds. Requires llvm 18, see [prerequisites](#sanitizers). + diff --git a/build.zig b/build.zig index e6f1b25970..cc7458d880 100644 --- a/build.zig +++ b/build.zig @@ -2,6 +2,7 @@ const std = @import("std"); const VERSION = "3.1"; +// TODO: x86_64-linux-gnu & aarch64-linux-gnu const targets: []const std.Target.Query = &.{ .{ .cpu_arch = .aarch64, .os_tag = .macos, .abi = null }, .{ .cpu_arch = .x86_64, .os_tag = .macos, .abi = null }, @@ -19,6 +20,8 @@ const BuildCfg = struct { mem_dbg: bool = false, c3dbg: bool = false, snapshot_validation: bool = false, + ubsan: bool = false, + asan: bool = false, }; pub fn build(b: *std.Build) !void { @@ -85,6 +88,26 @@ pub fn build(b: *std.Build) !void { "Binary name (Default: urbit)", ) orelse "urbit"; + // Sanitizers are not properly supported in musl => mac only + + const asan = if (target.query.isNative() and target.result.isDarwin()) + b.option( + bool, + "asan", + "Enable address sanitizer (native only, requires llvm@18)", + ) orelse false + else + false; + + const ubsan = if (target.query.isNative() and target.result.isDarwin()) + b.option( + bool, + "ubsan", + "Enable undefined behavior sanitizer (native only, requires llvm@18)", + ) orelse false + else + false; + // Parse short git rev // var file = try std.fs.cwd().openFile(".git/logs/HEAD", .{}); @@ -118,6 +141,8 @@ pub fn build(b: *std.Build) !void { .mem_dbg = mem_dbg, .c3dbg = c3dbg, .snapshot_validation = snapshot_validation, + .asan = asan, + .ubsan = ubsan, .include_test_steps = !all, }; @@ -156,12 +181,38 @@ fn build_single( try global_flags.appendSlice(cfg.flags); try global_flags.appendSlice(&.{ - "-fno-sanitize=all", "-g", "-Wall", "-Werror", }); + if (!cfg.asan and !cfg.ubsan) + try global_flags.appendSlice(&.{ + "-fno-sanitize=all", + }); + + if (cfg.asan and !cfg.ubsan) + try global_flags.appendSlice(&.{ + "-Wno-deprecated", + "-fsanitize=address", + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + + if (!cfg.asan and cfg.ubsan) + try global_flags.appendSlice(&.{ + "-fsanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + + if (cfg.asan and cfg.ubsan) + try global_flags.appendSlice(&.{ + "-Wno-deprecated", + "-fsanitize=address", + "-fsanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + // // CFLAGS for Urbit Libs and Binaries // @@ -861,6 +912,34 @@ fn build_single( urbit.linkLibC(); + if (t.isDarwin()) { + // Requires llvm@18 homebrew installation + if (cfg.asan or cfg.ubsan) + urbit.addLibraryPath(.{ + .cwd_relative = "/opt/homebrew/opt/llvm/lib/clang/18/lib/darwin", + }); + if (cfg.asan) urbit.linkSystemLibrary("clang_rt.asan_osx_dynamic"); + if (cfg.ubsan) urbit.linkSystemLibrary("clang_rt.ubsan_osx_dynamic"); + } + + if (t.os.tag == .linux) { + // Requires llvm-18 and clang-18 installation + if (cfg.asan or cfg.ubsan) + urbit.addLibraryPath(.{ + .cwd_relative = "/usr/lib/clang/18/lib/linux", + }); + if (t.cpu.arch == .x86_64) { + if (cfg.asan) urbit.linkSystemLibrary("clang_rt.asan-x86_64"); + if (cfg.ubsan) + urbit.linkSystemLibrary("clang_rt.ubsan_standalone-x86_64"); + } + if (t.cpu.arch == .aarch64) { + if (cfg.asan) urbit.linkSystemLibrary("clang_rt.asan-aarch64"); + if (cfg.ubsan) + urbit.linkSystemLibrary("clang_rt.ubsan_standalone-aarch64"); + } + } + urbit.linkLibrary(vere); urbit.linkLibrary(pkg_noun); urbit.linkLibrary(pkg_c3); diff --git a/pkg/c3/portable.h b/pkg/c3/portable.h index 4a507a8e3e..eeee55cc22 100644 --- a/pkg/c3/portable.h +++ b/pkg/c3/portable.h @@ -129,7 +129,11 @@ # define U3_OS_LoomBits 30 # elif defined(U3_OS_osx) # ifdef __LP64__ -# define U3_OS_LoomBase 0x28000000000 +# ifdef ASAN_ENABLED +# define U3_OS_LoomBase 0x728000000000 +# else +# define U3_OS_LoomBase 0x28000000000 +# endif # else # define U3_OS_LoomBase 0x4000000 # endif