Browse Source

Support `-sanitize:<string>` for `address`, `memory`, `thread` for LLVM 17

gingerBill 1 year ago
parent
commit
2160484b62
3 changed files with 52 additions and 1 deletions
  1. 16 0
      src/build_settings.cpp
  2. 17 1
      src/llvm_backend.cpp
  3. 19 0
      src/main.cpp

+ 16 - 0
src/build_settings.cpp

@@ -264,6 +264,14 @@ u64 get_vet_flag_from_name(String const &name) {
 }
 
 
+enum SanitizerFlags : u32 {
+	SanitizerFlag_NONE = 0,
+	SanitizerFlag_Address = 1u<<0,
+	SanitizerFlag_Memory  = 1u<<1,
+	SanitizerFlag_Thread  = 1u<<2,
+};
+
+
 
 // This stores the information for the specify architecture of this build
 struct BuildContext {
@@ -305,6 +313,7 @@ struct BuildContext {
 	String pdb_filepath;
 
 	u64 vet_flags;
+	u32 sanitizer_flags;
 
 	bool   has_resource;
 	String link_flags;
@@ -1738,6 +1747,13 @@ gb_internal bool init_build_paths(String init_filename) {
 		return false;
 	}
 
+	if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
+		if (build_context.metrics.os != TargetOs_linux) {
+			gb_printf_err("-sanitize:memory is only supported on linux\n");
+			return false;
+		}
+	}
+
 
 	if (bc->target_features_string.len != 0) {
 		enable_target_feature({}, bc->target_features_string);

+ 17 - 1
src/llvm_backend.cpp

@@ -1478,12 +1478,28 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
 		passes = gb_string_appendc(passes, "default<O0>");
 		break;
 	case 1:
-		passes = gb_string_appendc(passes, "default<O1>");
+		passes = gb_string_appendc(passes, "default<Os>");
 		break;
 	case 2:
 		passes = gb_string_appendc(passes, "default<O2>");
 		break;
 	}
+
+	// asan - Linux, Darwin, Windows
+	// msan - linux
+	// tsan - Linux, Darwin
+	// ubsan - Linux, Darwin, Windows (NOT SUPPORTED WITH LLVM C-API)
+
+	if (build_context.sanitizer_flags & SanitizerFlag_Address) {
+		passes = gb_string_appendc(passes, ",asan");
+	}
+	if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
+		passes = gb_string_appendc(passes, ",msan");
+	}
+	if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
+		passes = gb_string_appendc(passes, ",tsan");
+	}
+
 	LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes, wd->target_machine, pb_options);
 	defer (LLVMConsumeError(llvm_err));
 	if (llvm_err != nullptr) {

+ 19 - 0
src/main.cpp

@@ -300,6 +300,8 @@ enum BuildFlagKind {
 
 	BuildFlag_Tilde,
 
+	BuildFlag_Sanitize,
+
 #if defined(GB_SYSTEM_WINDOWS)
 	BuildFlag_IgnoreVsSearch,
 	BuildFlag_ResourceFile,
@@ -486,6 +488,8 @@ gb_internal bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
 #endif
 
+	add_flag(&build_flags, BuildFlag_Sanitize,                str_lit("sanitize"),                  BuildFlagParam_String,  Command__does_build, true);
+
 #if defined(GB_SYSTEM_WINDOWS)
 	add_flag(&build_flags, BuildFlag_IgnoreVsSearch,          str_lit("ignore-vs-search"),          BuildFlagParam_None,    Command__does_build);
 	add_flag(&build_flags, BuildFlag_ResourceFile,            str_lit("resource"),                  BuildFlagParam_String,  Command__does_build);
@@ -1194,6 +1198,21 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							build_context.tilde_backend = true;
 							break;
 
+						case BuildFlag_Sanitize:
+							GB_ASSERT(value.kind == ExactValue_String);
+
+							if (str_eq_ignore_case(value.value_string, str_lit("address"))) {
+								build_context.sanitizer_flags |= SanitizerFlag_Address;
+							} else if (str_eq_ignore_case(value.value_string, str_lit("memory"))) {
+								build_context.sanitizer_flags |= SanitizerFlag_Memory;
+							} else if (str_eq_ignore_case(value.value_string, str_lit("thread"))) {
+								build_context.sanitizer_flags |= SanitizerFlag_Thread;
+							} else {
+								gb_printf_err("-sanitize:<string> options are 'address', 'memory', and 'thread'\n");
+								bad_flags = true;
+							}
+							break;
+
 					#if defined(GB_SYSTEM_WINDOWS)
 						case BuildFlag_IgnoreVsSearch: {
 							GB_ASSERT(value.kind == ExactValue_Invalid);