ソースを参照

Enable all sanitizers on FreeBSD

Feoramund 3 ヶ月 前
コミット
6c5b96948e
3 ファイル変更34 行追加10 行削除
  1. 6 6
      src/build_settings.cpp
  2. 12 0
      src/linker.cpp
  3. 16 4
      src/llvm_backend.cpp

+ 6 - 6
src/build_settings.cpp

@@ -2303,9 +2303,10 @@ gb_internal bool init_build_paths(String init_filename) {
 		case TargetOs_windows:
 		case TargetOs_linux:
 		case TargetOs_darwin:
+		case TargetOs_freebsd:
 			break;
 		default:
-			gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n");
+			gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n");
 			return false;
 		}
 	}
@@ -2313,12 +2314,10 @@ gb_internal bool init_build_paths(String init_filename) {
 	if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
 		switch (build_context.metrics.os) {
 		case TargetOs_linux:
+		case TargetOs_freebsd:
 			break;
 		default:
-			gb_printf_err("-sanitize:memory is only supported on linux\n");
-			return false;
-		}
-		if (build_context.metrics.os != TargetOs_linux) {
+			gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n");
 			return false;
 		}
 	}
@@ -2327,9 +2326,10 @@ gb_internal bool init_build_paths(String init_filename) {
 		switch (build_context.metrics.os) {
 		case TargetOs_linux:
 		case TargetOs_darwin:
+		case TargetOs_freebsd:
 			break;
 		default:
-			gb_printf_err("-sanitize:thread is only supported on linux and darwin\n");
+			gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n");
 			return false;
 		}
 	}

+ 12 - 0
src/linker.cpp

@@ -802,6 +802,18 @@ try_cross_linking:;
 					link_settings = gb_string_appendc(link_settings, "-e _main ");
 				}
 			} else if (build_context.metrics.os == TargetOs_freebsd) {
+				if (build_context.sanitizer_flags & (SanitizerFlag_Address | SanitizerFlag_Memory)) {
+					// It's imperative that `pthread` is linked before `libc`,
+					// otherwise ASan/MSan will be unable to call `pthread_key_create`
+					// because FreeBSD's `libthr` implementation of `pthread`
+					// needs to replace the relevant stubs first.
+					//
+					// (Presumably TSan implements its own `pthread` interface,
+					//  which is why it isn't required.)
+					//
+					// See: https://reviews.llvm.org/D39254
+					platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread ");
+				}
 				// FreeBSD pkg installs third-party shared libraries in /usr/local/lib.
 				platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-L/usr/local/lib ");
 			} else if (build_context.metrics.os == TargetOs_openbsd) {

+ 16 - 4
src/llvm_backend.cpp

@@ -3425,36 +3425,48 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 
 
 	if (build_context.sanitizer_flags & SanitizerFlag_Address) {
-		if (build_context.metrics.os == TargetOs_windows) {
+		switch (build_context.metrics.os) {
+		case TargetOs_windows: {
 			auto paths = array_make<String>(heap_allocator(), 0, 1);
 			String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib"));
 			array_add(&paths, path);
 			Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib"));
 			array_add(&gen->foreign_libraries, lib);
-		} else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
+		} break;
+		case TargetOs_darwin:
+		case TargetOs_linux:
+		case TargetOs_freebsd:
 			if (!build_context.extra_linker_flags.text) {
 				build_context.extra_linker_flags = str_lit("-fsanitize=address");
 			} else {
 				build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address"));
 			}
+			break;
 		}
 	}
 	if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
-		if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
+		switch (build_context.metrics.os) {
+		case TargetOs_linux:
+		case TargetOs_freebsd:
 			if (!build_context.extra_linker_flags.text) {
 				build_context.extra_linker_flags = str_lit("-fsanitize=memory");
 			} else {
 				build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory"));
 			}
+			break;
 		}
 	}
 	if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
-		if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
+		switch (build_context.metrics.os) {
+		case TargetOs_darwin:
+		case TargetOs_linux:
+		case TargetOs_freebsd:
 			if (!build_context.extra_linker_flags.text) {
 				build_context.extra_linker_flags = str_lit("-fsanitize=thread");
 			} else {
 				build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread"));
 			}
+			break;
 		}
 	}