diff --git a/releasenotes.md b/releasenotes.md index 5dc191476..944c72f86 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -16,6 +16,9 @@ - Remove `.allocator = allocator` syntax for functions. - Remove `@operator(construct)`. +### Fixes +- Fix address sanitizer to work on MachO targets (e.g. MacOS). + ## 0.6.8 Change list ### Changes / improvements diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 621833c87..bbb89f98b 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -160,6 +160,7 @@ static LLVMValueRef llvm_emit_macho_xtor(GenContext *c, LLVMValueRef *list, cons scratch_buffer_append(name); LLVMValueRef array = LLVMConstArray(c->xtor_entry_type, list, vec_size(list)); LLVMValueRef global = LLVMAddGlobal(c->module, LLVMTypeOf(array), scratch_buffer_to_string()); + LLVMSetNoSanitizeAddress(global); scratch_buffer_clear(); scratch_buffer_append("__DATA,__"); scratch_buffer_append(name); @@ -196,6 +197,7 @@ void llvm_emit_constructors_and_destructors(GenContext *c) LLVMValueRef entry = LLVMConstNamedStruct(c->xtor_entry_type, vals, 3); LLVMValueRef array = LLVMConstArray(c->xtor_entry_type, &entry, 1); LLVMValueRef global_dtor = LLVMAddGlobal(c->module, LLVMTypeOf(array), "llvm.global_dtors"); + LLVMSetNoSanitizeAddress(global_dtor); LLVMSetLinkage(global_dtor, LLVMAppendingLinkage); LLVMSetInitializer(global_dtor, array); vals[1] = runtime_start; @@ -205,6 +207,7 @@ EMIT_CTORS: if (len == 0) return; array = LLVMConstArray(c->xtor_entry_type, ctors, len); LLVMValueRef global_ctor = LLVMAddGlobal(c->module, LLVMTypeOf(array), "llvm.global_ctors"); + LLVMSetNoSanitizeAddress(global_ctor); LLVMSetLinkage(global_ctor, LLVMAppendingLinkage); LLVMSetInitializer(global_ctor, array); return; diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 8ba48e253..ce84144f2 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -578,6 +578,7 @@ void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs) } LLVMValueRef array = LLVMConstArray(entry_type, entries, len); LLVMValueRef global = LLVMAddGlobal(c->module, LLVMTypeOf(array), "$c3_dynamic"); + LLVMSetNoSanitizeAddress(global); LLVMSetLinkage(global, LLVMInternalLinkage); LLVMSetInitializer(global, array); LLVMSetSection(global, "__DATA,__c3_dynamic"); diff --git a/test/test_suite/dynamic/dynamic_tracing.c3t b/test/test_suite/dynamic/dynamic_tracing.c3t index c1f0482e1..eb6cb6b86 100644 --- a/test/test_suite/dynamic/dynamic_tracing.c3t +++ b/test/test_suite/dynamic/dynamic_tracing.c3t @@ -62,5 +62,5 @@ fn void main() { @"$ct.test.Ba" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"$ct.test.Ca" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 -@"$c3_dynamic" = internal global [3 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Aa.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Aa" to i64) }, { ptr, ptr, i64 } { ptr @test.Ba.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ba" to i64) }, { ptr, ptr, i64 } { ptr @test.Ca.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ca" to i64) }], section "__DATA,__c3_dynamic", align 8 -@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_retain, ptr null }] +@"$c3_dynamic" = internal global [3 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Aa.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Aa" to i64) }, { ptr, ptr, i64 } { ptr @test.Ba.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ba" to i64) }, { ptr, ptr, i64 } { ptr @test.Ca.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ca" to i64) }], section "__DATA,__c3_dynamic", no_sanitize_address, align 8 +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_retain, ptr null }], no_sanitize_address diff --git a/test/test_suite/dynamic/inherit_macos.c3t b/test/test_suite/dynamic/inherit_macos.c3t index cb62b34df..792f9b960 100644 --- a/test/test_suite/dynamic/inherit_macos.c3t +++ b/test/test_suite/dynamic/inherit_macos.c3t @@ -48,7 +48,7 @@ fn void main() @.func = internal constant [5 x i8] c"main\00", align 1 @std.core.builtin.panic = extern_weak global ptr, align 8 @"$sel.hello" = linkonce_odr constant [6 x i8] c"hello\00", align 1 -@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @inherit.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }, { ptr, ptr, i64 } { ptr @inherit.Test.hello, ptr @"$sel.hello", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }], section "__DATA,__c3_dynamic", align 8 +@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @inherit.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }, { ptr, ptr, i64 } { ptr @inherit.Test.hello, ptr @"$sel.hello", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }], section "__DATA,__c3_dynamic", no_sanitize_address, align 8 define void @inherit.Test.tesT(ptr %0) #0 { entry: diff --git a/test/test_suite/dynamic/overlapping_function_macos.c3t b/test/test_suite/dynamic/overlapping_function_macos.c3t index a49c8a18a..4d9d33473 100644 --- a/test/test_suite/dynamic/overlapping_function_macos.c3t +++ b/test/test_suite/dynamic/overlapping_function_macos.c3t @@ -42,7 +42,7 @@ fn void main() @.func = internal constant [5 x i8] c"main\00", align 1 @std.core.builtin.panic = extern_weak global ptr, align 8 @"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 -@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }, { ptr, ptr, i64 } { ptr @overlap.Test.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }], section "__DATA,__c3_dynamic", align 8 +@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }, { ptr, ptr, i64 } { ptr @overlap.Test.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }], section "__DATA,__c3_dynamic", no_sanitize_address, align 8 ; Function Attrs: nounwind uwtable define void @overlap.Test.tesT(ptr %0) #0 { diff --git a/test/test_suite/stdlib/map_macos.c3t b/test/test_suite/stdlib/map_macos.c3t index 33cba557c..667393588 100644 --- a/test/test_suite/stdlib/map_macos.c3t +++ b/test/test_suite/stdlib/map_macos.c3t @@ -53,7 +53,7 @@ fn void main() /* #expect: test.ll @"$sel.to_new_string" = linkonce_odr constant [14 x i8] c"to_new_string\00", align 1 -@"$c3_dynamic" = internal global [1 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Foo.to_new_string, ptr @"$sel.to_new_string", i64 ptrtoint (ptr @"$ct.test.Foo" to i64) }], section "__DATA,__c3_dynamic", align 8 +@"$c3_dynamic" = internal global [1 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Foo.to_new_string, ptr @"$sel.to_new_string", i64 ptrtoint (ptr @"$ct.test.Foo" to i64) }], section "__DATA,__c3_dynamic", no_sanitize_address, align 8 define { ptr, i64 } @test.Foo.to_new_string(ptr %0, i64 %1, ptr %2) #0 { entry: diff --git a/wrapper/include/c3_llvm.h b/wrapper/include/c3_llvm.h index 377f8b160..8862ebb9e 100644 --- a/wrapper/include/c3_llvm.h +++ b/wrapper/include/c3_llvm.h @@ -78,6 +78,7 @@ LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal); void LLVMBuilderSetFastMathFlags(LLVMBuilderRef Builder, FastMathOption option); void LLVMSetDSOLocal(LLVMValueRef Global, bool value); void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array); +void LLVMSetNoSanitizeAddress(LLVMValueRef Global); #ifdef __cplusplus } diff --git a/wrapper/src/wrapper.cpp b/wrapper/src/wrapper.cpp index 81ee9a0e4..4f502e57f 100644 --- a/wrapper/src/wrapper.cpp +++ b/wrapper/src/wrapper.cpp @@ -318,6 +318,13 @@ void LLVMSetDSOLocal(LLVMValueRef Global, bool value) llvm::unwrap(Global)->setDSOLocal(value); } +void LLVMSetNoSanitizeAddress(LLVMValueRef Global) +{ + auto global = llvm::unwrap(Global); + auto data = global->getSanitizerMetadata(); + data.NoAddress = 1; + global->setSanitizerMetadata(data); +} void LLVMBuilderSetFastMathFlags(LLVMBuilderRef Builder, FastMathOption option) { llvm::FastMathFlags math_flags {};